问题
在继承父类的 delegate 之后子类又取名 delegate 后,系统会报一个 warning 如下:
Auto property synthesis will not synthesize property 'delegate'; it will be implemented by its superclass, use @dynamic to acknowledge intention复制代码
原因
通过声明属性,我们可以很简单的为一个成员变量定义其是否是只读的还是读写的,是否是原子操作的等等特性,也就是说如果说封装是为成员变量套了一层壳的话,那么@property关键字做的事情就是预定义这层壳是个什么样子的壳,然后通过@sythesize关键字生成真正的壳并把这个壳套在实际的成员变量上(如果没有定义这个成员变量该关键字也可以自动生成对应的成员变量)。当然这层壳包括了自动生成的 get/set 方法。
在最开始的时候,我们在代码中写了 @property 对应的就要写一个 @sythesize ,在苹果使用了 LLVM 作为编译器以后,如果我们没有写@sythesize,编译器就会为我们自动的生成一个@sythesize property = _property。这个特性叫做 Auto property synthesize。
说了这么多,现在我们来回头看看问题的关键,当我们想覆盖父类的属性并做一些修改的时候,Auto property synthesize 这个特性就有点不知道该干嘛了,这个时候他选择不跑出来为我们干活,所以编译器就不会自动生成 @sythesize property = _property,但是子类总得有个壳啊,人家都有 @property 了,怎么办?直接拿过来父类的壳复制一份不管三七二十一套在子类的成员变量身上。注意,有些情况下这会产生运行时的 crash。
解决
-
方法一: 所以遇到这个问题怎么解决?在子类中显式的声明一个 @synthesize name = _name;就好,这样子类就会如愿的产生他的壳,编译器也不纠结了,就去掉了 warning,从此,天下太平~
-
方法二:
@dynamic delegate;- (id)delegate{ id curDelegate = [super delegate]; return curDelegate;}- (void)setDelegate:(id )delegate{ [super setDelegate:delegate];}复制代码
延伸:@dynamic 与 @synthesize 区别
@synthesize 和 @dynamic 这两种方法应该都过时了,目前用法只单用 @property 就可以了。
旧式的写法是,在 @property 声明属性后,可以有 @synthesize 或者 @dynamic 两种实现方式的选择。 使用 @property+@synthesize 方式,能够让编译器在编译期间自动生成 setter/getter 这两个方法,配合属性声明使用。但是,当你自己又写了一遍 setter 或 getter 或者两个都重写了之后,你自己写的方法会被调用,而编译器生成的方法会被屏蔽。
使用 @property+@dynamic 方式,在编译期间没有生成 setter/getter 这两个方法,你想要使用这个属性需要自己重新写一遍 setter/getter 方法,不写也不产生编译警告。