昨天看了公眾號SwiftGG翻譯組
的文章《Swift:讓人眼前一亮的初始化方式》,自己動手敲了一篇,只能說,手感真特么爽。
先看看比較普通的寫法,最普通的就不說了,先看這種通過Block創建對象的寫法,優點:代碼整合在一個閉包里面,可讀性強。
let _ = { () -> UILabel in
let label = UILabel()
view.addSubview(label)
label.text = "myLabel"
label.font = UIFont.systemFont(ofSize: 18)
label.center = self.view.center
label.bounds = CGRect.init(x: 0, y: 0, width: 100, height: 50)
return label
}()
但如果要在一個ViewDidLoad
創建多個Label呢,那多個閉包里面怎么給相應的Label命名呢?都叫label
還是不同的命名呢?這是強迫癥和選擇困難癥并發的節奏。
接著看下面的寫法,在Block外初始化一個對象,再傳進閉包進行設值,統一用$0取參數對象,不用再去煩如何命名了。當然也可以命名,參考后文的寫法
不過有個缺點:里面的$0沒法自動聯想出屬性,手敲幾行代碼你就會藍瘦香菇
let _: UILabel = {
view.addSubview($0)
$0.text = "測試"
$0.font = UIFont.systemFont(ofSize: 18)
$0.center = self.view.center
$0.bounds = CGRect.init(x: 0, y: 0, width: 100, height: 50)
return $0
}(UILabel())
大概理解上面的代碼后,接著再看使用Then協議庫的初始化寫法,比上面的代碼更簡潔,不用寫return了,而且里面的$0還能自動聯想。優點:暫時沒有吐槽點
// 1.0 帶參數,可自行命名
let _ = UILabel().then_Any { (label) in
label.backgroundColor = .blue
label.font = UIFont.systemFont(ofSize: 18)
label.textAlignment = .center
label.text = "Then協議庫寫法_1.0"
label.frame = CGRect.init(x: 20, y: 200, width: 150, height: 40)
// 不會循環引用(已測試)
self.view.addSubview(label)
}
// 1.1 (推薦)無參數,無需命名,用$0取參數,可自動聯想屬性(推薦)
let _ = UILabel().then_Any {
$0.backgroundColor = .blue
$0.font = UIFont.systemFont(ofSize: 18)
$0.textAlignment = .center
$0.text = "Then庫寫法_1.1"
$0.frame = CGRect.init(x: 200, y: 260, width: 150, height: 40)
self.view.addSubview($0)
}
// 2.0 帶參數,可自行命名
let label_AnyO = UILabel().then { (label) in
label.backgroundColor = .blue
label.font = UIFont.systemFont(ofSize: 18)
label.textAlignment = .center
label.text = "Then庫寫法_2.0"
label.frame = CGRect.init(x: 200, y: 260, width: 150, height: 40)
}
self.view.addSubview(label_AnyO)
// 2.1 (推薦)無參數,無需命名,用$0取參數,可自動聯想屬性
let _ = UILabel().then {
$0.backgroundColor = .blue
$0.font = UIFont.systemFont(ofSize: 18)
$0.textAlignment = .center
$0.text = "Then庫寫法_2.1"
$0.frame = CGRect.init(x: 200, y: 260, width: 150, height: 40)
self.view.addSubview($0)
}
/// 栗子:某工廠方法
class func label(withFrame frame: CGRect, text: String?, font: UIFont) -> UILabel {
return UILabel.init(frame: frame).then(block: { (label) in
label.text = text
label.textColor = UIColor.black
label.backgroundColor = UIColor.white
label.font = font
})
}
其實Then協議庫只有十幾行代碼,但是能帶來非常好的體驗感,簡約實用,不會出現循環引用。下面的代碼可以復制到一個swift file中,直接用。
import Foundation
public protocol Then {}
extension Then where Self: Any {
public func then_Any( block: (inout Self) -> Void) -> Self {
var copy = self
block(©)
return copy
}
}
extension Then where Self: AnyObject {
public func then( block: (Self) -> Void) -> Self {
block(self)
return self
}
}
extension NSObject: Then {}
我所有Swift3.0練習Demo都放到了Github上,并且在不斷更新。
Swift3.0朝圣之路-全集地址