Created by CyanHall.com
on 11/25/2020
, Last updated: 04/30/2021.
👉 Star me if it’s helpful.
👉 Star me if it’s helpful.
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 ""
}
More