delegate 繼承問題

yangcg_掘金發表於2018-08-07

問題

在繼承父類的 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<FatherDelegte>)delegate
{
    id curDelegate = [super delegate];
    return curDelegate;
}

- (void)setDelegate:(id<FatherDelegte>)delegate
{
    [super setDelegate:delegate];
}
複製程式碼

延伸:@dynamic 與 @synthesize 區別

@synthesize@dynamic 這兩種方法應該都過時了,目前用法只單用 @property 就可以了。

舊式的寫法是,在 @property 宣告屬性後,可以有 @synthesize 或者 @dynamic 兩種實現方式的選擇。 使用 @property+@synthesize 方式,能夠讓編譯器在編譯期間自動生成 setter/getter 這兩個方法,配合屬性宣告使用。但是,當你自己又寫了一遍 setter 或 getter 或者兩個都重寫了之後,你自己寫的方法會被呼叫,而編譯器生成的方法會被遮蔽。

使用 @property+@dynamic 方式,在編譯期間沒有生成 setter/getter 這兩個方法,你想要使用這個屬性需要自己重新寫一遍 setter/getter 方法,不寫也不產生編譯警告。

相關文章