更新记录
时间 | 版本修改 |
---|---|
2020年4月3日 | 初版 |
2020年4月17日 | 详细描述了实现"协议中的属性"的问题 |
新建iOS工程去掉storyBoard
- 去掉storyBoard的3个步骤,参考iOS 开发之删除 storyboard
- 遇到不能识别selector的错误,-[AppDelegate setWindow:]: unrecognized selector sent to instance
- 参考iOS13生命周期的改动,需要给AppDelegate类添加一个属性:
@property (strong, nonatomic) UIWindow * window;
- 去掉storyBoard之后黑屏的问题,参考关于xcode11新建项目的黑屏那点事
一个小插曲
- 给
AppDelegate
添加window
属性时,直接添加了匿名分类中,报错:Illegal redeclaration of property in class extension 'AppDelegate' (attribute must be 'readwrite', while its primary must be 'readonly')
- 参考Xcode中出现Illegal redeclaration of property in class extension,该属性重复声明了。
- 但是为什么可以放置在.h文件,而不能放置在匿名分类里面呢?
- 参考能否向Protocol中添加属性?
- 结论
- 协议中的属性,声明了setter方法和getter方法。
- 匿名分类中添加属性,但是不会自动生成setter方法和getter方法。
上述问题总结
- 协议中的属性(即property)其实只声明了setter方法和getter方法,并没有实例变量。(想一下通用编程模式中接口的概念,是指某个类型实现了某些接口,而接口本身是不含有数据的。【注:这里的接口实质上就是iOS中所说的“协议”】)
- 协议中的方法都是对外公开的
- 匿名分类(即类扩展)中的属性,都是不对外公开(即private的)。
- 所以将协议中的属性,在匿名分类中实现,是一件非常奇怪的事情。因为协议本身声明了这个属性是public的,而匿名分类中又声明该属性是private的。所以编译器会报错,不知道该怎么处理。
- 如果想躲过编译器的报错,可以在头文件中声明该属性为readonly, 在匿名分类中声明该属性为readwrite。
- 但是在子类中修改协议(或者基类)的属性的对外权限时,是有警告的:
Attribute 'readonly' of property 'window' restricts attribute 'readwrite' of property inherited from 'UIApplicationDelegate'
- 但是在子类中修改协议(或者基类)的属性的对外权限时,是有警告的:
- 或者在头文件中直接声明该属性(就相当于继承了协议的setter方法和getter方法),并且也声明了一个实例变量。
- 与上述同等的做法,就是加入
@synthesize
声明。
如果根视图没有铺满全屏
写在后面的话
- 我第二次新建XCode demo的时候,仍然遇到了很多个问题,幸好之前都在此记录下了之前遇到的问题及解决方法。
- 如果有读者的demo无法正常运行的话,建议参考上述提及的每一个参考链接,都照着做一遍,就可以进入Hello World了!