在編寫一個自定義相冊的功能的時候,因爲須要繼承 UINavigationController
寫一個ImagePickerViewController
,同時ImagePickerViewController
又須要和其餘的類進行溝通,因此很天然的,ImagePickerViewController類
就須要有一個delegate
屬性,並且須要要求這個屬性是一個實現了自定義的ImagePickerViewControllerDelegate
協議的屬性,那麼這個時候問題就來了:父類是已經有一個這樣的屬性的。直接這麼寫編譯器就會給出一個 warning:app
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,今後,天下太平~