inheritance属性,setter在从readonly读取inheritance的属性时不合成

当我使用一个属性时,我发现了一个奇怪的行为,它被inheritance为readonly,并且在inheritance的类中被重新声明为readwrite

@interface A : NSObject @property (nonatomic, strong, readonly) NSObject * someProperty; @end 

Bh

 @interface B : A // no matter if here // @property (nonatomic, strong, readwrite) NSObject * someProperty; - (void)foo; @end 

Bm

 @interface B() // no matter if here @property (nonatomic, strong, readwrite) NSObject * someProperty; @end @implementation B - (void)foo { NSLog(@"%@", self.someProperty); // crash here with unrecognized selector setSomeProperty: self.someProperty = [NSObject new]; } @end 

调用

 self.someProperty = [NSObject new]; 

导致代码崩溃在无法识别的select器“setSomeProperty:”

调查显示,即使宣布为readwrite,看起来二传手也没有被合成

为什么发生这种情况? 编译器没有指出任何警告发生,也没有发现任何地方这种行为logging

添加@synthesize指令到Bm文件,崩溃将消失:

 @synthesize someProperty = _someProperty; 

问题是因为在父类中声明属性是readonly所以没有为它设置合成器。 而子类inheritance这个行为。 即使你重新声明属性是在子类中readwrite的。 @synthesize命令将指示编译器再次生成类B的访问器方法。

希望这可以帮助!

在这里输入图像说明

我不能给你一个官方的参考,但这是我经历的:对于从超类inheritance的属性,编译器不会生成任何访问器方法。

在你的情况下,该属性在类A中声明为readonly ,以便编译器只创build一个getter方法。 B类中的重新声明不会创build任何额外的访问器方法。 原因可能是,B类不知道A如何实现属性(它不一定是一个实例variables)。

因此,子类中的属性声明只是对编译器的“承诺”,即getter和setter函数将在运行时可用(类似于@dynamic声明)。 如果没有setter,那么你会得到一个运行时exception。

因此,如果超类在公共接口中声明属性为只读属性,而在( 私有 )类扩展名中则为读写属性,则在子类中重新声明属性的用例将是:

 // Ah @interface A : NSObject @property (nonatomic, strong, readonly) NSObject * someProperty; @end // Am @interface A() @property (nonatomic, strong, readwrite) NSObject * someProperty; @end @implementation A @end 

在这种情况下,setter和getter都在类A中创build,而类B可以在其实现中重新声明该属性为读写。

Interesting Posts