Objective-C autosynthesis(自動合成)

WadeLiu威發表於2019-02-13

Objective-C 語言中可以用 @property 標記快速建立屬性,編譯器會自動生成 settergetter 方法,這個過程就叫自動合成。

此過程由編譯器在編譯期執行。

自動合成失效的情況

  • 同時重寫 settergetter
  • 重寫了只讀屬性 getter
  • 使用了 @dynamic 標記
  • protocol 中定義的所有屬性
  • category 中定義的所有屬性
  • 過載父類的屬性:當你在子類中過載了父類中的屬性,必須使用 @synthesize 來手動合成 ivar

@property

本質

@property = ivar(例項變數) + getter/setter(存取方法);
複製程式碼

作用

編譯器會自動生成 settergetter 方法,同時編譯器會自動新增所寫型別的的例項變數,並且在屬性名前面預設新增下劃線,作為例項變數的名字。

@property 對應的由兩個詞:@synthesize@dynamic

如果兩個詞都沒有寫,則預設為:

@synthesize var = _var;
@synthesize var;// 同上
複製程式碼

runtime 實現

我們每次增加一個屬性,系統都會在 ivar_list 中新增一個成員變數的描述,在 method_list 中增加 settergetter 方法的描述,在屬性列表中增加一個屬性的描述,然後計算該屬性在物件中的偏移量,然後給出 settergetter 方法對應的實現。

setter 方法中從偏移量的位置開始賦值,在 getter 方法中從偏移量開始取值。

為了能夠讀取正確位元組數,系統物件偏移量的指標型別進行了型別強轉。

@synthesize

作用

@synthesize 的作用就在於可以在編譯器自動編寫的時候指定這個自動新增的例項變數的名字。

例子

@interface


@interface testClass ()

@property (nonatomic, copy) NSString * aaa;

@end

複製程式碼

@implementation

@implementation testClass

// 指定aaa的例項變數為bbb
@synthesize aaa = bbb;

- (NSString *)aaa {
    // 使用的例項變數為bbb
    bbb = @"";
    return bbb;
}

- (void)setAaa:(NSString *)aaa {
    bbb = @"";
}
複製程式碼

@dynamic

作用

編譯器不會自動生成settergetter方法,由使用者自己實現。

如果使用者沒有提供 settergetter,編譯的時候沒有問題,但是當程式執行到settergetter方法時,程式會自動崩潰。

動態繫結
編譯的時候沒有問題,執行的時候才會找不到方法

解決崩潰方法

  • 通過 runtime 機制在執行時新增屬性的存取方法( runtime 的運用方法之一)
  • 刪掉 @dynamic
  • 實現未提供的存取方法

相關文章