iOS 屬性關(guān)鍵字進階篇

之前寫過 《iOS屬性關(guān)鍵字》基礎(chǔ)篇,便于初學(xué)者理解,但沒有從根本上去說明,屬性的本質(zhì),這次就更進一步說明

屬性的本質(zhì)

 ivar + getter + setter
  • ivar 實例變量
  • 存取方法(access method = getter + setter)

直白一點說,每個屬性本身就是一個實例的封裝,getter 和 setter 方法,就是這個實例開放給外界的外部接口,
我們可以根據(jù) getter 和 setter 方法,訪問這個實例。

舉個例子:

@interface Person : NSObject
@property NSString *firstName;
@property NSString *lastName;
@end

上述代碼寫出來的類與下面這種寫法等效:

@interface Person : NSObject
- (NSString *)firstName;
- (void)setFirstName:(NSString *)firstName;
- (NSString *)lastName;
- (void)setLastName:(NSString *)lastName;
@end

runtime 中對屬性的更新

property 在 runtime 中是 objc_property_t 定義如下:

typedef struct objc_property *objc_property_t;

而 objc_property 是一個結(jié)構(gòu)體,包括 name 和 attributes,定義如下:

struct property_t {
    const char *name;
    const char *attributes;
};

這這其中 attributes 本質(zhì)是 objc_property_attribute_t ,定義了 property 的一些屬性,定義如下:

/// Defines a property attribute
typedef struct {
    const char *name;           /**< The name of the attribute */
    const char *value;          /**< The value of the attribute (usually empty) */
} objc_property_attribute_t;

而 attributes 的具體內(nèi)容是什么呢?其實,包括:類型,原子性,內(nèi)存語義和對應(yīng)的實例變量。

例如:

我們定義一個 string 的 property @property (nonatomic, copy) NSString *string;,
通過 property_getAttributes(property)獲取到 attributes 并打印出來之后的結(jié)果為 T@"NSString",C,N,V_string

其中 T 就代表類型,可參閱 Type Encodings C 就代表 Copy,N 代表 nonatomic,V 就代表對于的實例變量。

ivar、getter、setter 是如何生成并添加到這個類中的?

“自動合成”( autosynthesis)

完成屬性定義后,編譯器會自動編寫訪問這些屬性所需的方法,此過程叫做“自動合成”( autosynthesis )。需要強調(diào)的是,這個過程由編譯器在編譯期執(zhí)行,所以編輯器里看不到這些“合成方法”( synthesized method )的源代碼。除了生成方法代碼 getter、setter 之外,編譯器還要自動向類中添加適當(dāng)類型的實例變量,并且在屬性名前面加下劃線,以此作為實例變量的名字。在前例中,會生成兩個實例變量,其名稱分別為 _firstName 與 _lastName。也可以在類的實現(xiàn)代碼里通過 @synthesize 語法來指定實例變量的名字.

@implementation Person
@synthesize firstName = _myFirstName;
@synthesize lastName = _myLastName;
@end

其實相關(guān)的代碼,會大致生成了五個東西

  • OBJC_IVAR_$類名$屬性名稱 :該屬性的“偏移量” (offset),這個偏移量是“硬編碼” (hardcode),表示該變量距離存放對象的內(nèi)存區(qū)域的起始地址有多遠。
  • setter 與 getter 方法對應(yīng)的實現(xiàn)函數(shù)
  • ivar_list :成員變量列表
  • method_list :方法列表
  • prop_list :屬性列表

我們每次在增加一個屬性:

  • 系統(tǒng)首先會在 ivar_list 中添加一個成員變量的描述
  • 在 method_list 中增加 setter 與 getter 方法的描述,
  • 在屬性列表中增加一個屬性的描述

然后計算該屬性在對象中的偏移量,然后給出 setter 與 getter 方法對應(yīng)的實現(xiàn),在 setter 方法中從偏移量的位置開始賦值,在 getter 方法中從偏移量開始取值 , 為了能夠讀取正確字節(jié)數(shù),系統(tǒng)對象偏移量的指針類型進行了類型強轉(zhuǎn).

反過來推一推一個程序如何從空到有

這里為什么會用 “空” ,而不是 “無”,因為我們所有的創(chuàng)造都不是完全從無開始的,像一個人也不是從無到有的,一個人的誕生也是從空到有,必須有“空”,至于什么是 “空”,就不贅述。
一個程序的誕生,必須先要有內(nèi)存空間,這個內(nèi)存空間就是整個程序的原點,也是它的空。而如何讓空的東西變成有,我們就要賦予它規(guī)則,有規(guī)則后,才能一生二,二生三,三生萬物,這便是天地最根本的道理。而程序,也是遵循這個道理,更透徹的說,一段程序,就是承載一段有規(guī)律 0 和 1 的集合。

??本質(zhì)總是這樣簡單又復(fù)雜


結(jié)束語

實際上,這本身就是一種封裝,便于開發(fā)者更簡單實現(xiàn),基礎(chǔ)類的定義;這也是為什么 OC 代碼的編寫方式 和 C 代碼編寫方式的不一樣的地方。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 對動物世界很了解的朋友應(yīng)該知道在螞蟻的世界里分工明確協(xié)作能力很強,那只懶懶的螞蟻在做什么呢,保持觀察,敏銳的思考,...
    九月fine閱讀 288評論 0 1
  • 1黃昏下,你牽著夕陽落幕 黃昏來臨的時候,我看見天邊都金黃色,我發(fā)著信息告訴你遠方的姑娘,我想念你。我回來的路上,...
    朱迪勞閱讀 316評論 0 0
  • talk into end up catch wind of Musk comes off asa much mo...
    谷音sp閱讀 431評論 0 0

友情鏈接更多精彩內(nèi)容