CyanHall.com 创建于 2020-11-25, 上次更新:2021-04-30。
👉  github shields 如果有用请点赞。

1. cocopods

    brew install cocopods # dont install via gem, it use ruby 2.6 and may cause problems under MI chip.
pod deintegrate
pod install

# source 'https://github.com/CocoaPods/Specs.git'
source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
project 'ProjectName.xcodeproj'
platform :ios, '12.0'
#use_frameworks!
inhibit_all_warnings!

target 'ProjectName' do
  use_frameworks!
    pod 'Alamofire', '~> 5.5'

end

post_install do |pi|
    pi.pods_project.targets.each do |t|
      t.build_configurations.each do |config|
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
       config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
      end
    end
end
  

2. fix: /Library/Ruby/Gems/2.6.0/gems/ffi-1.15.5/lib/ffi/library.rb:275: [BUG] Bus Error at 0x00000001026f0000

    sudo arch -x86_64 gem install ffi
arch -x86_64 pod install
  

3. fix: building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

    [Project] => Build Settings => Architectures => Excluded Architectures => Debug => Any iOS Simulator SKD => arm64
# Maybe error: No such module 'Framework' error will come out without this
  

4. fix: Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099

    xcrun simctl spawn booted log config --mode "level:off"  --subsystem com.apple.CoreTelephony
  

5. add Objective-C Bridging Header

    // File -> New File -> Header File
// Build Settings, find "Objective-C Bridging Header"
// $(SRCROOT)/
$(PROJECT_NAME)/$(SWIFT_MODULE_NAME)-Bridging-Header.h
  

6. Xcode Key Binding

    Xcode Preferences -> Navigation -> Command-click on Code: Jumps to Definition
  

7. Xcode Swift Switch Index

    Xcode Preferences -> Text editing > Indentation -> Indent switch/case labels - [checked]swift
  

8. Hide strange unwanted Xcode logs

    // 1 - From Xcode menu open: Product > Scheme > Edit Scheme/
//  2 - On your Environment Variables set OS_ACTIVITY_MODE = disable
// Note: this will hide log from NSLog(), use print() instead.
  

9. fix load xib view error: class is not key value coding-compliant for the key

    // Connecting the outlet to the view, and not the file owner
  

10. fix extra padding on header of grouped UITableView

    // dont use .grouped, use .plain instead!
  

11. Access Address

    expr -l Swift -- import [MyTestProject]
expr -l Swift -- let $vc = unsafeBitCast(0x7fad22c066d0, to: ViewController.self)
expr -l Swift -- $vc.frame

// more: https://github.com/kastiglione/swift_po
  

12. Log with file function line info

    func Log(_ message: Any, file: String = #file, function: String = #function, line: Int = #line ) {
    print("[Log (NSString(string: file).lastPathComponent) (function) (line)]: (message)")
}
  

13. Swift DEBUG flag

    Target => Build Settings => Other Swift Flags => -D DEBUG
  

14. Xcode breakpoins not working

    
  

15.

    offsetY = (someView.superview?.convert(someView.frame.origin, to: nil).y)!
  

16. Basic

    var sampleDict: Dictionary<String, Any> = [:]
var sampleList: [String] = []

// List Dict Keys
Array(dict.keys) 
dict.forEach {
  print("($0.key):($0.value)")
}
list.enumerated().forEach { (index, element) in
    ...
}
let array = [(2, "is"), (0, "Hello"), (1, "this"), (3, "Ben")]
let sortedArray = array.sort { $0.0 < $1.0 }

print(sortedArray) // [(0, "Hello"), (1, "this"), (2, "is"), (3, "Ben")]

// Dynamic Access
@IBOutlet weak var view1: UIView!
let view1Alias = self.value(forKey: "view1") as! UIView

Double(5.5).rounded(.down) // floor: 5
Double(5.5).rounded(.up) // ceil: 6
  

17. String

    let datetimeStr = "2020-11-29 15:03:14"
let index = datetimeStr.index(datetimeStr.startIndex, offsetBy: 10)
let dateStr = String(datetimeStr[..<index])
print(dateStr) // 2020-11-29

let someString = "1, 2, 3, 4"
let substrings = someString.components(separatedBy: ", ")
substrings.joined(separator: ", ")

// Slice String
String(Array("123456")[...1]) // "12"
String(Array("123456")[1...]) // "23456"
String(Array("123456")[1...3]) // 234

// 1 to 01
String(format: "%02d", 1)

// Print Data
String(decoding: data, as: UTF8.self)

["1", "2"].joined(separator: ",") // "1,2"
[1, 2].map{String($0)}.joined(separator: ",") // "1,2"
  

18. Decode codable

    func Decode<T: Codable> (_ t: T.Type, _ data: Data) -> T? {
    let decoder = JSONDecoder()
    do {
        let model = try decoder.decode(T.self, from: data)
        return model
    } catch {
        Log("Decode error:(error)")
    }
    return nil
}
let model = Decode(User.self, data)
  

19. Load json file data

    func loadJsonFile(file: String) -> Any {
    let path = Bundle.main.path(forResource: file, ofType: "json")
    let data = NSData.init(contentsOfFile: path!)
    let json = try! JSONSerialization.jsonObject(with: data! as Data, options: .allowFragments)
    return json
}
  

20. check Empty or Nil

    extension Optional where Wrapped: Collection {
    var isEmptyOrNil: Bool {
        return self?.isEmpty ?? true
    }
}

someStr.isEmptyOrNil
  

21. Self class name

    String(describing: self)
  

22. Dictionary

    // Check key exist
dict.keys.contains(key)
  

23. Loop

    for i in 1..<7 {
  print(i)
}
// 1 2 3 4 5 6

let items = [
    "name": "Cyanhall",
    "author": "Cyanhall"
]
for item in items {
    print("(item.value): (item.key)")
}
for item in items.reversed() {
    print("(item.value): (item.key)")
}
for (index, item) in items.enumerated() {
  print("(index). (item.value): (item.key)")
}
  

24. Button

    sampleBtn.setTitleColor(.balck, for: .normal)
sampleBtn.setImage(UIImage.init(named: "sample_icon"), for: .normal)
  

25. UILabel

    label.font = UIFont.systemFont(ofSize: 10) 
label.font.pointSize // 10
  

26. Calculate String Width/Height

    someLabel.intrinsicContentSize.width
someStr.boundingRect(with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: 15)], context: nil).size.height
  

27. UIImage

    // Compress Image
UIImage.init(data: UIImageJPEGRepresentation(image, 0.7)!)!
  

28. UITextField

    // left padding 
let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = UITextFieldViewMode.Always
textField.leftView = spacerView
  

29. UIAlertController

    extension UIViewController {
    func showAlert(title: String?, message: String?, style: UIAlertController.Style, actionTypeList: Array<UIAlertAction.Style>, actionTitleList: Array<String>, block: IntBlock) {
        let alert = UIAlertController.init(title: title, message: message, preferredStyle: style)
        actionTitleList.enumerated().forEach { (index, actionTitle) in
            let action = UIAlertAction.init(title: actionTitle, style: actionTypeList[index]) { _ in
                block?(index)
            }
            alert.addAction(action)
        }
        self.present(alert, animated: true, completion: nil)
    }
}
  

30. Status Bar Style

    override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}
  

31. cornerRadius

    let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 10
// Top right corner, Top left corner respectively
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
  

32. Adding shadow to top of UIView

    enum VerticalLocation: String {
    case bottom
    case top  
}

extension UIView {
    func addShadow(location: VerticalLocation, color: UIColor = .black, opacity: Float = 0.5, radius: CGFloat = 5.0) {
        switch location {
        case .bottom:
             addShadow(offset: CGSize(width: 0, height: 10), color: color, opacity: opacity, radius: radius)
        case .top:
            addShadow(offset: CGSize(width: 0, height: -10), color: color, opacity: opacity, radius: radius)
        }
    }

    func addShadow(offset: CGSize, color: UIColor = .black, opacity: Float = 0.5, radius: CGFloat = 5.0) {
        self.layer.masksToBounds = false
        self.layer.shadowColor = color.cgColor
        self.layer.shadowOffset = offset
        self.layer.shadowOpacity = opacity
        self.layer.shadowRadius = radius
    }
}
  

33. navigationBar

    // Hide navigationBar
self.navigationController?.navigationBar.isHidden = true
  

34. Load Xib Resources

    let vc = MyViewController() //  VC with Xib Resources
vc.loadViewIfNeeded() // Load Xib Resources
  

35. navigationBar navigationItems

    override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]

    let editImage    = UIImage(named: "edit")!
    let searchImage  = UIImage(named: "search")
    let editButton   = UIBarButtonItem(image: editImage,  style: .plain, target: self, action: #selector(didTapEditButton(sender:)))
    let searchButton = UIBarButtonItem(image: searchImage,  style: .plain, target: self, action: #selector(didTapSearchButton(sender:)))
    let textItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(clickSaveAction))
    textItem.setTitleTextAttributes([.foregroundColor: UIColor.red], for: .normal) // Set text color
    navigationItem.rightBarButtonItems = [editButton, searchButton, textItem]

    let backItem = UIBarButtonItem(image: UIImage(named: "icon_back") , style: .plain, target: self, action: #selector(clickBack))
    self.navigationItem.leftBarButtonItem = backItem
}
@objc func didTapEditButton(sender: AnyObject){

}

@objc func didTapSearchButton(sender: AnyObject){

}
@objc func clickSaveAction() -> Void{

}
@objc func clickBack() {
    self.navigationController?.popViewController(animated: true)
}
  

36. Notification

    let NotiCenter = NotificationCenter.default

extension Notification.Name {
    static let LOGIN = Notification.Name("LOGIN") 
    static let LOGOUT = Notification.Name("LOGOUT")
}
// Objective-C Interpolation
@objc public extension NSNotification {
    static var LOGIN: String {
        return "LOGIN"
    }
    static var LOGOUT: String {
        return "LOGOUT"
    }
}

NotiCenter.post(name: .LOGIN, object: data)
[[NSNotificationCenter defaultCenter] postNotificationName:NSNotification.LOGIN object:nil];

NotiCenter.addObserver(
  self,
  selector: #selector(self.handllLogin),
  name: .LOGIN,
  object: nil)

@objc func handllLogin(notification: NSNotification?){
  print(notification.object) // data
}

// No need
deinit {
  NotiCenter.removeObserver(self)
}
  

37. Execute code on Main UI Thread

    DispatchQueue.global(qos: .background).async {
  // Execute code on Background Thread
}
DispatchQueue.main.async {
  // Execute code on Main UI Thread
}
  

38. Delay code

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
    DispatchQueue.main.async {
        self.scrolling = false
    }
}
  

39. Cookies

    // Get Cookies
let cookieData: Data = try? NSKeyedArchiver.archivedData(withRootObject: HTTPCookieStorage.shared.cookies!, requiringSecureCoding: false)

// Set Cookies
let cookies = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(cookieData) as? Array<HTTPCookie>
let cookieStorage = HTTPCookieStorage.shared
cookies.forEach { cookie in
  cookieStorage.setCookie(cookie)
}
  

40. ImageView load Image

    import Kingfisher

let url = URL(string: "[path]")
self.avatarImage.kf.setImage(with: url)
  

41. Pragma Mark

    // MARK: Swift

#pragma mark - Objective-C
  

42. Click Block

    typealias VoidBlock = (()->())?
typealias IntBlock = ((_ index: Int)->())?
typealias BoolBlock = ((_ yes: Bool)->())?
typealias ModelBlock = ((_ model: Model)->())?

class SomeClass {
  var someBlock: ModelBlock = nil
  func someFunc() {
    // ...
    // get model
    self.someBlock?(model)
  }
}

let someIns = SomeClass()
someInc.someBlock = {model in 
    // 
}
  

43. UICollectionView/UITableView inside UIScrollView

    let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapOnScollView))
tap.numberOfTapsRequired = 1
myScollView.addGestureRecognizer(tap)

@objc func tapOnScollView(_ sender: UITapGestureRecognizer) {
    let touchLocation = sender.location(ofTouch: 0, in: self.collectionView)
    let indexPath = self.collectionView.indexPathForItem(at: touchLocation)
    if indexPath != nil {
        // Do somthing 
    }
}
  

44. Date String Extension

    // String+Extension.swift
func FormatDateTime(formartString:String, fromFormat:String = "yyyy-MM-dd HH:mm:ss") -> String {
    if self.count == 0 {return ""}
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = fromFormat
    let date = dateFormatter.date(from: self)
    
    let timeFormatter = DateFormatter()
    timeFormatter.dateFormat = formartString
    let strNowTime = timeFormatter.string(from: date! ) as String
    return strNowTime
}

func TimeToNow() -> String {
    //获取当前的时间戳
    let currentTime = Date().timeIntervalSince1970
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    let date = dateFormatter.date(from: self)
    
    let dateStamp:TimeInterval = date!.timeIntervalSince1970
    
    let dateStr:Double = Double(dateStamp)
    //时间差
    let reduceTime : TimeInterval = currentTime - dateStr
    //时间差小于60秒
    if reduceTime < 60 {
        return "刚刚"
    }
    //时间差大于一分钟小于60分钟内
    let mins = Int(reduceTime / 60)
    if mins < 60 {
        return "(mins)分钟前"
    }
    let hours = Int(reduceTime / 3600)
    if hours < 24 {
        return "(hours)小时前"
    }
    let days = Int(reduceTime / 3600 / 24)
    if days < 30 {
        return "(days)天前"
    }
    //不满足上述条件---或者是未来日期-----直接返回日期
    return self.FormatDateTime(formartString: "yyyy年MM月dd日 HH:mm:ss")
}

// 2020-11-30 12:00:00 => 2020-11-30
let date = "2020-11-30 12:00:00"
date.FormatDateTime(formartString: "yyyy-MM-dd")
date.TimeToNow()
  

45. ML Model

    import Foundation
import Cocoa // import UIKit
import Vision
func getHPfromImage (image: NSImage) -> String {
    var final = ""
    let model = try! VNCoreMLModel(for: DotaHP().model)
    let request = VNCoreMLRequest(model: model, completionHandler: {request, error in
        guard let results = request.results else {
            print("Unable to classify image.
(error!.localizedDescription)")
            return
        }
        let classifications = results as! [VNClassificationObservation]
    
        if classifications.isEmpty {
            print("Nothing recognized.")
        } else {
            // Display top classifications ranked by confidence in the UI.
            let topClassifications = classifications.prefix(1)
            let descriptions = topClassifications.map { classification -> String in
                // Formats the classification for display; e.g. "(0.37) cliff, drop, drop-off".
                if final == "" {
                    final = classification.identifier
                }
               return String(format: "  (%.2f) %@", classification.confidence, classification.identifier)
            }
            print("Classification:
" + descriptions.joined(separator: "
"))
        }

    })
    request.imageCropAndScaleOption = .centerCrop
    guard let cgImg = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
           fatalError("can't convert image")
       }
    let ciImage = CIImage.init(cgImage: cgImg)

    let handler = VNImageRequestHandler(ciImage: ciImage, orientation: .up)
    do {
        try handler.perform([request])
    } catch {
        print("Failed to perform classification.
(error.localizedDescription)")
    }
    return final
}
  

46. SFSpeechRecognizer

    func getSubtitles () -> String {
    let request = SFSpeechURLRecognitionRequest(url: NSURL.init(fileURLWithPath: "/Users/JeOam/Git/CyanhallPy/videos/1.mp4") as URL)
    let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh_Hans_CN"))!
    SFSpeechRecognizer.requestAuthorization { (status) in
        OperationQueue.main.addOperation {
            print(status)
        }
    }
    speechRecognizer.recognitionTask(with: request) { (result, error) in
        print(result, error)
    }
    print(speechRecognizer.isAvailable)
    return ""
}
  

1. cocopods

    brew install cocopods # dont install via gem, it use ruby 2.6 and may cause problems under MI chip.
pod deintegrate
pod install

# source 'https://github.com/CocoaPods/Specs.git'
source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
project 'ProjectName.xcodeproj'
platform :ios, '12.0'
#use_frameworks!
inhibit_all_warnings!

target 'ProjectName' do
  use_frameworks!
    pod 'Alamofire', '~> 5.5'

end

post_install do |pi|
    pi.pods_project.targets.each do |t|
      t.build_configurations.each do |config|
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
       config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
      end
    end
end
  

3. fix: building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

    [Project] => Build Settings => Architectures => Excluded Architectures => Debug => Any iOS Simulator SKD => arm64
# Maybe error: No such module 'Framework' error will come out without this
  

5. add Objective-C Bridging Header

    // File -> New File -> Header File
// Build Settings, find "Objective-C Bridging Header"
// $(SRCROOT)/
$(PROJECT_NAME)/$(SWIFT_MODULE_NAME)-Bridging-Header.h
  

7. Xcode Swift Switch Index

    Xcode Preferences -> Text editing > Indentation -> Indent switch/case labels - [checked]swift
  

9. fix load xib view error: class is not key value coding-compliant for the key

    // Connecting the outlet to the view, and not the file owner
  

11. Access Address

    expr -l Swift -- import [MyTestProject]
expr -l Swift -- let $vc = unsafeBitCast(0x7fad22c066d0, to: ViewController.self)
expr -l Swift -- $vc.frame

// more: https://github.com/kastiglione/swift_po
  

13. Swift DEBUG flag

    Target => Build Settings => Other Swift Flags => -D DEBUG
  

15.

    offsetY = (someView.superview?.convert(someView.frame.origin, to: nil).y)!
  

17. String

    let datetimeStr = "2020-11-29 15:03:14"
let index = datetimeStr.index(datetimeStr.startIndex, offsetBy: 10)
let dateStr = String(datetimeStr[..<index])
print(dateStr) // 2020-11-29

let someString = "1, 2, 3, 4"
let substrings = someString.components(separatedBy: ", ")
substrings.joined(separator: ", ")

// Slice String
String(Array("123456")[...1]) // "12"
String(Array("123456")[1...]) // "23456"
String(Array("123456")[1...3]) // 234

// 1 to 01
String(format: "%02d", 1)

// Print Data
String(decoding: data, as: UTF8.self)

["1", "2"].joined(separator: ",") // "1,2"
[1, 2].map{String($0)}.joined(separator: ",") // "1,2"
  

19. Load json file data

    func loadJsonFile(file: String) -> Any {
    let path = Bundle.main.path(forResource: file, ofType: "json")
    let data = NSData.init(contentsOfFile: path!)
    let json = try! JSONSerialization.jsonObject(with: data! as Data, options: .allowFragments)
    return json
}
  

21. Self class name

    String(describing: self)
  

23. Loop

    for i in 1..<7 {
  print(i)
}
// 1 2 3 4 5 6

let items = [
    "name": "Cyanhall",
    "author": "Cyanhall"
]
for item in items {
    print("(item.value): (item.key)")
}
for item in items.reversed() {
    print("(item.value): (item.key)")
}
for (index, item) in items.enumerated() {
  print("(index). (item.value): (item.key)")
}
  

25. UILabel

    label.font = UIFont.systemFont(ofSize: 10) 
label.font.pointSize // 10
  

27. UIImage

    // Compress Image
UIImage.init(data: UIImageJPEGRepresentation(image, 0.7)!)!
  

29. UIAlertController

    extension UIViewController {
    func showAlert(title: String?, message: String?, style: UIAlertController.Style, actionTypeList: Array<UIAlertAction.Style>, actionTitleList: Array<String>, block: IntBlock) {
        let alert = UIAlertController.init(title: title, message: message, preferredStyle: style)
        actionTitleList.enumerated().forEach { (index, actionTitle) in
            let action = UIAlertAction.init(title: actionTitle, style: actionTypeList[index]) { _ in
                block?(index)
            }
            alert.addAction(action)
        }
        self.present(alert, animated: true, completion: nil)
    }
}
  

31. cornerRadius

    let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 10
// Top right corner, Top left corner respectively
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
  

33. navigationBar

    // Hide navigationBar
self.navigationController?.navigationBar.isHidden = true
  

35. navigationBar navigationItems

    override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]

    let editImage    = UIImage(named: "edit")!
    let searchImage  = UIImage(named: "search")
    let editButton   = UIBarButtonItem(image: editImage,  style: .plain, target: self, action: #selector(didTapEditButton(sender:)))
    let searchButton = UIBarButtonItem(image: searchImage,  style: .plain, target: self, action: #selector(didTapSearchButton(sender:)))
    let textItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(clickSaveAction))
    textItem.setTitleTextAttributes([.foregroundColor: UIColor.red], for: .normal) // Set text color
    navigationItem.rightBarButtonItems = [editButton, searchButton, textItem]

    let backItem = UIBarButtonItem(image: UIImage(named: "icon_back") , style: .plain, target: self, action: #selector(clickBack))
    self.navigationItem.leftBarButtonItem = backItem
}
@objc func didTapEditButton(sender: AnyObject){

}

@objc func didTapSearchButton(sender: AnyObject){

}
@objc func clickSaveAction() -> Void{

}
@objc func clickBack() {
    self.navigationController?.popViewController(animated: true)
}
  

37. Execute code on Main UI Thread

    DispatchQueue.global(qos: .background).async {
  // Execute code on Background Thread
}
DispatchQueue.main.async {
  // Execute code on Main UI Thread
}
  

39. Cookies

    // Get Cookies
let cookieData: Data = try? NSKeyedArchiver.archivedData(withRootObject: HTTPCookieStorage.shared.cookies!, requiringSecureCoding: false)

// Set Cookies
let cookies = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(cookieData) as? Array<HTTPCookie>
let cookieStorage = HTTPCookieStorage.shared
cookies.forEach { cookie in
  cookieStorage.setCookie(cookie)
}
  

41. Pragma Mark

    // MARK: Swift

#pragma mark - Objective-C
  

43. UICollectionView/UITableView inside UIScrollView

    let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapOnScollView))
tap.numberOfTapsRequired = 1
myScollView.addGestureRecognizer(tap)

@objc func tapOnScollView(_ sender: UITapGestureRecognizer) {
    let touchLocation = sender.location(ofTouch: 0, in: self.collectionView)
    let indexPath = self.collectionView.indexPathForItem(at: touchLocation)
    if indexPath != nil {
        // Do somthing 
    }
}
  

45. ML Model

    import Foundation
import Cocoa // import UIKit
import Vision
func getHPfromImage (image: NSImage) -> String {
    var final = ""
    let model = try! VNCoreMLModel(for: DotaHP().model)
    let request = VNCoreMLRequest(model: model, completionHandler: {request, error in
        guard let results = request.results else {
            print("Unable to classify image.
(error!.localizedDescription)")
            return
        }
        let classifications = results as! [VNClassificationObservation]
    
        if classifications.isEmpty {
            print("Nothing recognized.")
        } else {
            // Display top classifications ranked by confidence in the UI.
            let topClassifications = classifications.prefix(1)
            let descriptions = topClassifications.map { classification -> String in
                // Formats the classification for display; e.g. "(0.37) cliff, drop, drop-off".
                if final == "" {
                    final = classification.identifier
                }
               return String(format: "  (%.2f) %@", classification.confidence, classification.identifier)
            }
            print("Classification:
" + descriptions.joined(separator: "
"))
        }

    })
    request.imageCropAndScaleOption = .centerCrop
    guard let cgImg = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
           fatalError("can't convert image")
       }
    let ciImage = CIImage.init(cgImage: cgImg)

    let handler = VNImageRequestHandler(ciImage: ciImage, orientation: .up)
    do {
        try handler.perform([request])
    } catch {
        print("Failed to perform classification.
(error.localizedDescription)")
    }
    return final
}
  

2. fix: /Library/Ruby/Gems/2.6.0/gems/ffi-1.15.5/lib/ffi/library.rb:275: [BUG] Bus Error at 0x00000001026f0000

    sudo arch -x86_64 gem install ffi
arch -x86_64 pod install
  

4. fix: Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099

    xcrun simctl spawn booted log config --mode "level:off"  --subsystem com.apple.CoreTelephony
  

6. Xcode Key Binding

    Xcode Preferences -> Navigation -> Command-click on Code: Jumps to Definition
  

8. Hide strange unwanted Xcode logs

    // 1 - From Xcode menu open: Product > Scheme > Edit Scheme/
//  2 - On your Environment Variables set OS_ACTIVITY_MODE = disable
// Note: this will hide log from NSLog(), use print() instead.
  

10. fix extra padding on header of grouped UITableView

    // dont use .grouped, use .plain instead!
  

12. Log with file function line info

    func Log(_ message: Any, file: String = #file, function: String = #function, line: Int = #line ) {
    print("[Log (NSString(string: file).lastPathComponent) (function) (line)]: (message)")
}
  

14. Xcode breakpoins not working

    
  

16. Basic

    var sampleDict: Dictionary<String, Any> = [:]
var sampleList: [String] = []

// List Dict Keys
Array(dict.keys) 
dict.forEach {
  print("($0.key):($0.value)")
}
list.enumerated().forEach { (index, element) in
    ...
}
let array = [(2, "is"), (0, "Hello"), (1, "this"), (3, "Ben")]
let sortedArray = array.sort { $0.0 < $1.0 }

print(sortedArray) // [(0, "Hello"), (1, "this"), (2, "is"), (3, "Ben")]

// Dynamic Access
@IBOutlet weak var view1: UIView!
let view1Alias = self.value(forKey: "view1") as! UIView

Double(5.5).rounded(.down) // floor: 5
Double(5.5).rounded(.up) // ceil: 6
  

18. Decode codable

    func Decode<T: Codable> (_ t: T.Type, _ data: Data) -> T? {
    let decoder = JSONDecoder()
    do {
        let model = try decoder.decode(T.self, from: data)
        return model
    } catch {
        Log("Decode error:(error)")
    }
    return nil
}
let model = Decode(User.self, data)
  

20. check Empty or Nil

    extension Optional where Wrapped: Collection {
    var isEmptyOrNil: Bool {
        return self?.isEmpty ?? true
    }
}

someStr.isEmptyOrNil
  

22. Dictionary

    // Check key exist
dict.keys.contains(key)
  

24. Button

    sampleBtn.setTitleColor(.balck, for: .normal)
sampleBtn.setImage(UIImage.init(named: "sample_icon"), for: .normal)
  

26. Calculate String Width/Height

    someLabel.intrinsicContentSize.width
someStr.boundingRect(with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: 15)], context: nil).size.height
  

28. UITextField

    // left padding 
let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = UITextFieldViewMode.Always
textField.leftView = spacerView
  

30. Status Bar Style

    override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}
  

32. Adding shadow to top of UIView

    enum VerticalLocation: String {
    case bottom
    case top  
}

extension UIView {
    func addShadow(location: VerticalLocation, color: UIColor = .black, opacity: Float = 0.5, radius: CGFloat = 5.0) {
        switch location {
        case .bottom:
             addShadow(offset: CGSize(width: 0, height: 10), color: color, opacity: opacity, radius: radius)
        case .top:
            addShadow(offset: CGSize(width: 0, height: -10), color: color, opacity: opacity, radius: radius)
        }
    }

    func addShadow(offset: CGSize, color: UIColor = .black, opacity: Float = 0.5, radius: CGFloat = 5.0) {
        self.layer.masksToBounds = false
        self.layer.shadowColor = color.cgColor
        self.layer.shadowOffset = offset
        self.layer.shadowOpacity = opacity
        self.layer.shadowRadius = radius
    }
}
  

34. Load Xib Resources

    let vc = MyViewController() //  VC with Xib Resources
vc.loadViewIfNeeded() // Load Xib Resources
  

36. Notification

    let NotiCenter = NotificationCenter.default

extension Notification.Name {
    static let LOGIN = Notification.Name("LOGIN") 
    static let LOGOUT = Notification.Name("LOGOUT")
}
// Objective-C Interpolation
@objc public extension NSNotification {
    static var LOGIN: String {
        return "LOGIN"
    }
    static var LOGOUT: String {
        return "LOGOUT"
    }
}

NotiCenter.post(name: .LOGIN, object: data)
[[NSNotificationCenter defaultCenter] postNotificationName:NSNotification.LOGIN object:nil];

NotiCenter.addObserver(
  self,
  selector: #selector(self.handllLogin),
  name: .LOGIN,
  object: nil)

@objc func handllLogin(notification: NSNotification?){
  print(notification.object) // data
}

// No need
deinit {
  NotiCenter.removeObserver(self)
}
  

38. Delay code

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
    DispatchQueue.main.async {
        self.scrolling = false
    }
}
  

40. ImageView load Image

    import Kingfisher

let url = URL(string: "[path]")
self.avatarImage.kf.setImage(with: url)
  

42. Click Block

    typealias VoidBlock = (()->())?
typealias IntBlock = ((_ index: Int)->())?
typealias BoolBlock = ((_ yes: Bool)->())?
typealias ModelBlock = ((_ model: Model)->())?

class SomeClass {
  var someBlock: ModelBlock = nil
  func someFunc() {
    // ...
    // get model
    self.someBlock?(model)
  }
}

let someIns = SomeClass()
someInc.someBlock = {model in 
    // 
}
  

44. Date String Extension

    // String+Extension.swift
func FormatDateTime(formartString:String, fromFormat:String = "yyyy-MM-dd HH:mm:ss") -> String {
    if self.count == 0 {return ""}
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = fromFormat
    let date = dateFormatter.date(from: self)
    
    let timeFormatter = DateFormatter()
    timeFormatter.dateFormat = formartString
    let strNowTime = timeFormatter.string(from: date! ) as String
    return strNowTime
}

func TimeToNow() -> String {
    //获取当前的时间戳
    let currentTime = Date().timeIntervalSince1970
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    let date = dateFormatter.date(from: self)
    
    let dateStamp:TimeInterval = date!.timeIntervalSince1970
    
    let dateStr:Double = Double(dateStamp)
    //时间差
    let reduceTime : TimeInterval = currentTime - dateStr
    //时间差小于60秒
    if reduceTime < 60 {
        return "刚刚"
    }
    //时间差大于一分钟小于60分钟内
    let mins = Int(reduceTime / 60)
    if mins < 60 {
        return "(mins)分钟前"
    }
    let hours = Int(reduceTime / 3600)
    if hours < 24 {
        return "(hours)小时前"
    }
    let days = Int(reduceTime / 3600 / 24)
    if days < 30 {
        return "(days)天前"
    }
    //不满足上述条件---或者是未来日期-----直接返回日期
    return self.FormatDateTime(formartString: "yyyy年MM月dd日 HH:mm:ss")
}

// 2020-11-30 12:00:00 => 2020-11-30
let date = "2020-11-30 12:00:00"
date.FormatDateTime(formartString: "yyyy-MM-dd")
date.TimeToNow()
  

46. SFSpeechRecognizer

    func getSubtitles () -> String {
    let request = SFSpeechURLRecognitionRequest(url: NSURL.init(fileURLWithPath: "/Users/JeOam/Git/CyanhallPy/videos/1.mp4") as URL)
    let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh_Hans_CN"))!
    SFSpeechRecognizer.requestAuthorization { (status) in
        OperationQueue.main.addOperation {
            print(status)
        }
    }
    speechRecognizer.recognitionTask(with: request) { (result, error) in
        print(result, error)
    }
    print(speechRecognizer.isAvailable)
    return ""
}
  


Maitained by Cyanhall.com, Copy Rights @ CC BY-NC-SA 4.0     ExcelRoadMap