Swift学习笔记之初始化
阶段构造Swift 的构造过程分为两个阶段:
安全检查在构造的过程中, Swift 会进行四种安全检查。 安全检查 1
比如下面这段代码就是错误的: class Food { var name: String init(name: String) { self.name = name } } class RecipeIngredient: Food { var quantity: Int init(name: String,quantity: Int) { super.init(name: name) // ERROR! self.quantity = quantity } } 安全检查 2
比如下面这段代码就是错误的: class Food { var name: String init(name: String) { self.name = name } } class RecipeIngredient: Food { override init(name: String) { self.name = "WHY" // ERROR! super.init(name: name) } } 安全检查 3
比如下面这段代码就是错误的: class Food { var name: String init(name: String) { self.name = name } } class RecipeIngredient: Food { var quantity: Int init(name: String,quantity: Int) { self.quantity = quantity super.init(name: name) } override convenience init(name: String) { quantity = 2 // ERROR! self.init(name: name,quantity: 1) } } 安全检查 4
比如下面这段代码就是错误的: class Food { var name: String init(name: String) { self.name = name } } class RecipeIngredient: Food { var quantity: Int init(name: String,quantity: Int) { self.quantity = quantity println(self.name) // ERROR! super.init(name: name) } override convenience init(name: String) { self.init(name: name,quantity: 1) } } 蛋疼的初始化过程Swift 的初始化过程十分严格,刚从 OC 转过来的同仁可能习惯性的就写了这样的代码: class ViewController: UIViewController { private let animator: UIDynamicAnimator required init(coder aDecoder: NSCoder) { // ERROR: Property 'self.animator' not initialized at super.init call super.init(coder: aDecoder) animator = UIDynamicAnimator(referenceView: self.view) } } 是的它报错了!哦想起来了,要在 super 前面初始化自己的属性: class ViewController: UIViewController { private let animator: UIDynamicAnimator required init(coder aDecoder: NSCoder) { // use of property 'view' in base object before super.init initializes it animator = UIDynamicAnimator(referenceView: self.view) super.init(coder: aDecoder) } } 是的它又报错了!哦想起来了你不能在 view 的父类初始化之前调用这个属性。那就先不赋值吧: class ViewController: UIViewController { private let animator: UIDynamicAnimator required init(coder aDecoder: NSCoder) { animator = UIDynamicAnimator() super.init(coder: aDecoder) // ERROR: Cannot assign to the result of this expression animator.referenceView = self.view } } 坑爹啊不是,这个属性居然是只读的! 我们只好把属性设置成 class ViewController: UIViewController { private var animator: UIDynamicAnimator? required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func viewDidLoad() { super.viewDidLoad() animator = UIDynamicAnimator(referenceView: self.view) } } 这时 你以为这就完了?想太多。 由于是可选类型,所以在使用的时候需要解包: if let actualAnimator = animator { actualAnimator.addBehavior(UIGravityBehavior()) } 这太丑了,或者用强制解包: animator!.addBehavior(UIGravityBehavior()) 或者用可选链: animator?.addBehavior(UIGravityBehavior()) 都!太!low!了! 这时候不妨试试隐式解析可选类型: class ViewController: UIViewController { private var animator: UIDynamicAnimator! required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func viewDidLoad() { super.viewDidLoad() animator = UIDynamicAnimator(referenceView: self.view) } } 似乎好看多了。不过这并不是正确的打开方式,我觉得设计可选类型的工程师们应该不希望我们用这个方法,毕竟这更像是为了解决历史遗留包袱所做的妥协。 或许用 class ViewController: UIViewController { lazy private var animator: UIDynamicAnimator = { return UIDynamicAnimator(referenceView: self.view) }() required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func viewDidLoad() { super.viewDidLoad() animator.addBehavior(UIGravityBehavior()) } } References
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |