一,闭包&逃逸闭包。
定义一个闭包变量&常量,然后调用:
let escapingBlocks: (String) -> String = { (str: String) -> String in return str; } print(escapingBlocks("xxxx"));
定义一个包类型,并且初始化,然后调用:
typealias escapingBlock = (String) -> String; let testBlock: escapingBlock = { (s: String) -> String in return "hello \(s)" } print(testBlock("word!"));
逃逸闭包,概念,当一个函数中将一个闭包作为参数时,当前函数执行完之后(或者函数已经返回后),还没有去执行当前闭包,那么当前的闭包就是一个逃逸闭包,可以理解为逃逸出去了,没在本函数中进行执行,例如:
//定义一个包类型 typealias escapingBlock = (String) -> String; //然后定义一函数,参数为escapingBlock的闭包,并且是逃逸闭包,因为将其block进行了返回 func escapingFunc(blockPar: @escaping escapingBlock) -> escapingBlock { return blockPar; } // override func viewDidLoad() { super.viewDidLoad() //调用函数,接受返回的闭包。 let escB: escapingBlock = escapingFunc(blockPar: { (s: String) -> String in return "this is my escaping by string - \(s)" }); //调用返回的闭包 print(escB("是的是的。")); //以上等价于: let testBlock: escapingBlock = { (s: String) -> String in return "this is my escaping by string - \(s)" }; let blockByFunc = escapingFunc(blockPar: testBlock); print(blockByFunc("😔😔😔😔😔😔")); }
以上的闭包作为函数的参数,没有在函数内部进行执行,直接被返回了,所以在函数参数声明的时候,用@escaping去做了声明,这就是逃逸闭包。
二,Selector。以下第一种形式已经替代了第二种形式。
//1 var sel: Selector = #selector(repeatAction(_ :)); @objc func repeatAction(_ timer:Timer) -> Void { print("[] [] [] [] []"); } /*-------------------------*/ //2 override func viewDidLoad() { super.viewDidLoad() let sel: Selector = Selector(("selectorTest:")); self.perform(sel, with: "hello"); } @objc func selectorTest(_ params: Any) { print("oh oh ",params); }
三,中间件拦截消息,进行转发,防止循环引用。
import UIKit class SKProxy: NSObject { weak var target: NSObjectProtocol? static func SKProxyWithTarget(_ target:NSObjectProtocol) -> SKProxy{ let proxy = SKProxy(); proxy.target = target; return proxy; } override func forwardingTarget(for aSelector: Selector!) -> Any? { if target?.responds(to: aSelector) == true { return target; } return super.forwardingTarget(for: aSelector); } }
var timer: Timer? @objc func repeatAction(_ timer:Timer) -> Void { print("[] [] [] [] []"); } deinit { timer?.invalidate(); timer = nil; } override func viewDidLoad() { super.viewDidLoad() // let proxy: SKProxy = SKProxy.SKProxyWithTarget(self); timer = Timer.scheduledTimer(timeInterval: 1.0, target: proxy, selector: #selector(repeatAction(_:)), userInfo: nil, repeats: true); }
四,判断某个对象是否有实现某个Selector(SEL):
if target?.responds(to: aSelector) == true
五,rawValue获取枚举中属性,枚举类型中的真正值,例如,UIButton中的ButtonType类型,某一个输出值为custom,那么此类型的rawValue就是0:
public enum ButtonType : Int { case custom = 0 @available(iOS 7.0, *) case system = 1 case detailDisclosure = 2 }
六,Swift扩展中增加属性。
// // UIView+Radius.swift // SwiftProject // // Created by skyzizhu on 2020/12/27. // import Foundation import UIKit private var cornerRadisusKey = "cornerRadisusKey"; extension UIView { //设置上下左右圆角 var cornerRadisus: CGFloat { get{ return objc_getAssociatedObject(self, &cornerRadisusKey) as! CGFloat; } set(newValue){ objc_setAssociatedObject(self, &cornerRadisusKey, newValue, .OBJC_ASSOCIATION_ASSIGN); if newValue > 0.0 { setViewCornerRadisus(); } } } private func setViewCornerRadisus() -> Void { let maskPath: UIBezierPath = .init(roundedRect: bounds, cornerRadius: cornerRadisus); let maskLayer: CAShapeLayer = CAShapeLayer(); maskLayer.frame = bounds; maskLayer.path = maskPath.cgPath; layer.mask = maskLayer; } /// 使用,v.viewCornerRadisus(corners: UIRectCorner.init([.topLeft,.topRight]), cornerRadii: .init(width: 10, height: 10)); /// - Parameters: /// - corners: UIRectCorner /// - cornerRadii: CGSize /// - Returns: NONE func viewCornerRadisus(corners: UIRectCorner,cornerRadii: CGSize) -> Void { guard (corners.rawValue != 0) else { return; } let maskPath: UIBezierPath = .init(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: cornerRadii); let maskLayer: CAShapeLayer = CAShapeLayer(); maskLayer.frame = bounds; maskLayer.path = maskPath.cgPath; layer.mask = maskLayer; } }
七,编码中判断Swift版本。
#if swift(>=4.2) let KFRunLoopModeCommon = RunLoop.Mode.common #else let KFRunLoopModeCommon = RunLoopMode.commonModes #endif
八,变量的入口+动态派发机制,可让其进行KVO监听,例如:
@objc dynamic var isKeep: Bool = false;
九,泛型的使用场景。
// 定义泛型函数,接受一个泛型参数,要求该泛型类型必须继承Animal func AnimalRunPint<T:Animal>(animal:T) { animal.run() // 继承了Animal类的子类都有run方法可以调用 } AnimalRunPint(Dog()) // Dog run AnimalRunPint(Cat()) // Cat run
十,subscript。
subscript,可以给任意类型(枚举、结构体、类)增加下标功能,例如:
class scriptDemoClass { static subscript(_ par_1:Int,_ par_2:String) -> String { return String(format: "%d - %@", par_1,par_2); } subscript() -> Int { return 33; } } //调用 let scCla:scriptDemoClass = scriptDemoClass(); let str = scriptDemoClass[1,"这是我的数组"]; print(str); print(scCla[]); //可通过此,封装Userdefaults,例如: extension UserDefaults { static var udfs: UserDefaults { get { UserDefaults.standard; } } subscript(key: String) -> Any? { get { return object(forKey: key); } set { set(newValue, forKey: key); } } } // 使用: UserDefaults.udfs["memberID"] = "1231231231"; print(UserDefaults.udfs["memberID"]!);
十一,CATransition动画,可以实现某种所想要的动画效果。
let varView = self.view.viewWithTag(101); let tr: CATransition = CATransition(); tr.duration = 1.0; tr.type = .moveIn; tr.subtype = .fromBottom; tr.startProgress = 1.0; tr.endProgress = 0.1; varView?.layer.add(tr, forKey: "CATransitionKey");
十二,mutating,nonmutating关键字。此两关键字只能用于struct类型中,struct为值传递,为了确保值的唯一性和完整性,方法和通过mutating,nonmutating进行修饰。
通过mutating,nonmutating关键字进行修饰的方法,可在方法内部修饰结构体的值,这里的值可理解成结构体的属性值,例如:
struct structDemo { var _str: String? var str: String { get{"string"} nonmutating set{//这里的set方法会报错,不能够修改属性_str的值 //需用mutating进行修饰,默修饰认为mutating。 _str = newValue; } } mutating func change() -> Void {//这里可以修改str的值,因为mutating修饰 str = "1212"; } }
十三,swift中单例创建:
class SkyObject { private static let obj: SkyObject = SkyObject(); var val: Int = 0 static func manager() -> SkyObject { return obj; } static func shared(params: Int) -> SkyObject { obj.val = params; return obj; } }
十四,swift中的异常抛出及错误处理:
//定义错误类型 enum SKY_Error: Error { case error_first case error_second case error_third } //标记抛出错误、异常的函数 func printerOperate(toPrint value: Int) throws -> String { if value == 1 { throw SKY_Error.error_first; } else if value == 2 { throw SKY_Error.error_second; } else if value == 3 { throw SKY_Error.error_third; } return "success"; } /*异常处理的不同方式*/ //处理异常 - 1 do { let value: String = try printerOperate(toPrint: 1); print(value); } catch { print(error); }; //处理异常 - 2 do { let value: String = try printerOperate(toPrint: 2); print(value); } catch { print(error); } //处理异常 - 3 do { let value: String = try printerOperate(toPrint: 3); print(value); } catch SKY_Error.error_first { print("\(SKY_Error.error_first) - 错误1"); } catch SKY_Error.error_second { print("\(SKY_Error.error_second) - 错误2"); } catch SKY_Error.error_third { print("\(SKY_Error.error_third) - 错误3"); } catch { print("未知错误"); } //处理异常 - 4 let value = try? printerOperate(toPrint: 0); if let thisValue = value { print(thisValue); }