OC 中,覆盖属性会有怎么样的化学反应?

在编写一个自定义相册的功能的时候,因为须要继承 UINavigationController写一个ImagePickerViewController,同时ImagePickerViewController又须要和其余的类进行沟通,因此很天然的,ImagePickerViewController类就须要有一个delegate属性,并且须要要求这个属性是一个实现了自定义的ImagePickerViewControllerDelegate协议的属性,那么这个时候问题就来了:父类是已经有一个这样的属性的。直接这么写编译器就会给出一个 warningapp

Auto property synthesis will not synthesize property 'delegate'; it will be implemented by its superclass, use @dynamic to acknowledge intentionatom

诚然咱们能够经过声明一个相似delegateObj的属性来避开这个问题,不过为什么编译器会给出这个 warning 却值得研究。code

要想研究这个问题首先得从什么是属性开始讲起,在 oc 中属性就是给一个类的成员变量提供封装:orm

Objective-C properties offer a way to define the information that a class is intended to encapsulate。对象

经过声明属性,咱们能够很简单的为一个成员变量定义其是不是只读的仍是读写的,是不是原子操做的等等特性,也就是说若是说封装是为成员变量套了一层壳的话,那么 @property关键字作的事情就是预约义这层壳是个什么样子的壳,而后经过 @sythesize关键字生成真正的壳并把这个壳套在实际的成员变量上(若是没有定义这个成员变量该关键字也能够自动生成对应的成员变量)。固然这层壳包括了自动生成的 get set 方法。
在最开始的时候,咱们在代码中写了@property对应的就要写一个@sythesize,在苹果使用了 LLVM 做为编译器之后,若是咱们没有写 @sythesize,编译器就会为咱们自动的生成一个 @sythesize property = _property。这个特性叫作Auto property synthesize继承

说了这么多,如今咱们来回头看看问题的关键,当咱们想覆盖父类的属性并作一些修改的时候,Auto property synthesize这个特性就有点不知道该干吗了,这个时候他选择不跑出来为咱们干活,因此编译器就不会自动生成@sythesize property = _property,可是子类总得有个壳啊,人家都有@property了,怎么办?直接拿过来父类的壳复制一份无论三七二十一套在子类的成员变量身上。注意,有些状况下这会产生运行时的 crash,好比:
一个父类 Aget

@interface A : NSObject
@property(strong,nonatomic,readonly)NSString *name;

子类 Aa编译器

@interface Aa : A
@property(strong,nonatomic,readwrite)NSString *name;

这种状况下编译器会给出 warning:it

Auto property synthesis will not synthesize property 'name' because it is 'readwrite' but it will be synthesized 'readonly' via another propertyio

注意,虽然只给出了 warning,可是这个时候显然 Aa 中是不会自动生成 set 方法的,若是在代码中调用了 Aa 的实例对象的 set 方法,运行时就会 crash,crash 缘由是:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Aa setName:]: unrecognized selector sent to instance

因此遇到这个问题怎么解决?在子类中显式的声明一个@synthesize name = _name;就好,这样子类就会如愿的产生他的壳,编译器也不纠结了,就去掉了 warning,今后,天下太平~

相关文章
相关标签/搜索