最近我將 Xcode 升級到最新的 5.1,然後原本都沒事的原始碼,卻遇到了 property synthesis 相關的 error,錯誤訊息大概長得像這樣:
Warning: Auto property synthesis will not synthesize property 'XXX' because it is 'readwrite' but it will be synthesized 'readonly' via another property
花了一些時間,終於找到問題所在。
我有個 super-class,它有公開一些 readonly property,它的 sub-class 因為某些原因需要把這個 property 改成 readwrite。這應該是個蠻常見的使用情境,範例大致上長得像這樣:
// Super-class, .h
@interface Car : NSObject
@property (nonatomic, copy, readonly) NSString *name; // 只公開 readonly property
@end
// Super-class, .m
@implementation Car()
@property (nonatomic, copy, readwrite) NSString *name; // 實作時改成 readwrite property
@end
// Sub-class, .h
@interface Tesla : Car
@end
// Sub-class .m
@interface Tesla()
@property (nonatomic, copy, readwrite) NSString *name; // sub-class 因為有特別需求,所以將公開的 readonly property 改成 readwrite
@end
就是這樣的程式碼,會讓 name
property 出現 warning。原因是因為 compiler 讀取 sub-class 時,會發現 name
明明應該是個 readonly
property(super-class 講的),但你卻要將它設為 readwrite
property,所以 compiler 不知道該怎麼 auto synthesis。
但你知道 super-class 的實作,也會將這個 property 改成 readwrite
,因此你在 sub-class 的實作裡這樣子寫是不會有問題的。可是 compiler 不知道啊,這要怎麼辦呢?
你要告訴 compiler,要它不用擔心。那要怎麼告訴 compiler 呢?你需要的是 @dynamic
,它是一種給 compiler 的「承諾」,承諾它「雖然你現在不知道該怎麼辦,但是在 runtime 的時候你就會知道了」。所以只要把程式碼改成以下這樣就可以了:
// Sub-class .m
@implement Tesla
@dynamic name;
....
@end
以上,希望能幫到一些人 :-)