(iOS)Storyboard 与 initWithCoder -- designated initializer小结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/madongchunqiu/article/details/49702931

本文首发地址:http://blog.csdn.net/madongchunqiu/article/details/49702931


为了保证初始化的正确性,obj-c里面设计了Designated Initializer(指定初始化函数,下文简称DI)([1] Concepts in Objective-C Programming - Object Initialization),其目的在于保证当前class都能最终以某个函数进行初始化,从而避免部分成员变量不进行初始化的漏洞。这种做法被推荐为class设计时的best practice。swift则对DI进行了强制规定,并在编译阶段进行查错处理([2]The Swift Programming Language - Initialization)。

按照上面的设计思路,DI应该是有且只有一个才合理。然而在使用Storyboard进行设计时,我们会惊讶的发现DI并未被调用。怪!


今天详细读了文档,然后总结规律如下:

✅1. 一个class可以有多个DI ,虽然我觉得这样超极不合理
✅2. 在“非Storyboard”情况下,UIKit class仅有一个DI。当对其进行subclass时,此DI必须被调用([3]UIView Class Reference)
✅3. 在“Storyboard”情况下,UIKit class均使用initWithCoder作为其第二个DI。当对其进行subclass时,initWithCoder必须被调用([4]View Programming Guide for iOS)


-------分割线------

因此比较常用的UIKit subclass初始化,最好提供至少两个DI,如下:
A。对UIViewController而言,override以下两个DI,并在其中调用其super的相应DI
initWithNibName:bundle:
initWithCoder:

B。对UIView而言,override以下两个DI,并在其中调用其super的相应DI
initWithFrame:
initWithCoder:

C。对UITableViewCell而言,override以下两个DI,并在其中调用其super的相应DI
initWithStyle:reuseIdentifier:
initWithCoder:


-------分割线------


如果subclass不愿使用super的DI,需要创建自己的DI的话,则遵循以下原则(详见swift programming language文档)

i)subclass新的DI,需要直接调用super的DI
ii)subclass需override其super的原DI(已成为convenience initializer)(注1),并在其中调用新的DI
iii) subclass其余的convenience initializer,均需调用新的DI



(图片来自swift programming language)


注释

注1:关于subclass设计了新的DI后,对其super的原DI的处理,在obj-cswift中可以有不一样的处理:

obj-c中,subclass自动继承super的initializer,因此如果subclass使用了了新的DI,却不override其super的DI,则可能会出现初始化漏洞。(When you define a subclass, you must be able to identify the designated initializer of the superclass and invoke it in your subclass’s designated initializer through a message to super. You must also make sure that inherited initializers are covered in some way. 摘自([1]Concepts in Objective-C Programming - Object Initialization)

swift中,subclass不会自动继承super的initializer,因此可以不考虑这个问题。(Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default. 摘自([2]The Swift Programming Language - Initialization))


参考

[1] Concepts in Objective-C Programming - Object Initialization, https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/Initialization/Initialization.html

[2] The Swift Programming Language - Initialization, https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html

[3] UIView Class Reference, https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/

[4] View Programming Guide for iOS, https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html


猜你喜欢

转载自blog.csdn.net/madongchunqiu/article/details/49702931