1.Ivar
1.1 Ivar的內(nèi)存結(jié)構(gòu)
typedef struct objc_ivar *Ivar;
struct objc_ivar {
char *ivar_name? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;? // 變量名
char *ivar_type? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;? // 變量類型
int ivar_offset? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;? // 基地址偏移字節(jié)
#ifdef __LP64__
int space? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
#endif
}
1.2 Ivar操作若未,一般來說活烙,操作都是圍繞內(nèi)存模型來展開的属愤。
// 獲取成員變量名
const char * ivar_getName ( Ivar v );
// 獲取成員變量類型編碼
const char * ivar_getTypeEncoding ( Ivar v );
// 獲取成員變量的偏移量
ptrdiff_t ivar_getOffset ( Ivar v );
2揍诽,屬性
2.1 屬性定義
typedef struct objc_property *objc_property_t;
屬性的attribute愉适,objc_property_attribute_t犯助;
typedef struct {
const char *name;? ? ? ? ? // 特性名
const char *value;? ? ? ? ? // 特性值
} objc_property_attribute_t;
2.2 屬性操作。
// 獲取屬性名
const char * property_getName ( objc_property_t property );
// 獲取屬性特性描述字符串
const char * property_getAttributes ( objc_property_t property );
// 獲取屬性中指定的特性
char * property_copyAttributeValue ( objc_property_t property, const char *attributeName );//返回的char *在使用完后需要調(diào)用free()釋放维咸。
// 獲取屬性的特性列表
objc_property_attribute_t * property_copyAttributeList ( objc_property_t property, unsigned int *outCount );//返回值在使用完后需要調(diào)用free()釋放
3 關(guān)聯(lián)對(duì)象(Associated Object)
Objective-c類的category不能添加屬性剂买。原因是編譯器不會(huì)對(duì)category里的屬性自動(dòng)生成getter和setter方法。編譯器會(huì)提示:
@dynamic只能蒙騙編譯器癌蓖,不讓它有提示瞬哼。運(yùn)行時(shí)obj.name; obj.name = @"",都會(huì)崩潰。
避免崩潰的方法就只能手動(dòng)添加name的getter和setter方法租副。
重寫了getter和setter方法后坐慰,我們發(fā)現(xiàn)一個(gè)問題,對(duì)于這個(gè)name屬性用僧,有了方法结胀,但是沒有存儲(chǔ)name屬性值的成員變量。
runtime提供了關(guān)聯(lián)對(duì)象的機(jī)制责循,來提供存儲(chǔ)name屬性的"成員變量"糟港,這里加引號(hào),因?yàn)樗皇钦娴某蓡T變量沼死。
當(dāng)創(chuàng)建關(guān)聯(lián)對(duì)象的時(shí)候着逐,我們調(diào)用:
eg.?
objc_setAssociatedObject(self, &myKey, anObject, OBJC_ASSOCIATION_RETAIN);
最后一個(gè)參數(shù)用于指定關(guān)聯(lián)對(duì)象的內(nèi)存管理策略。策略一共包括以下幾種:
OBJC_ASSOCIATION_ASSIGN
OBJC_ASSOCIATION_RETAIN_NONATOMIC
OBJC_ASSOCIATION_COPY_NONATOMIC
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY
其中,retain的作用相當(dāng)于strong耸别,增加對(duì)象的引用計(jì)數(shù)健芭。
關(guān)聯(lián)對(duì)象很好的解決了category里面不能添加屬性的尷尬。當(dāng)然秀姐,關(guān)聯(lián)對(duì)象的功能不僅僅如此慈迈。應(yīng)該還是回到關(guān)聯(lián)對(duì)象本來的面目,就是給對(duì)象關(guān)聯(lián)另外一個(gè)對(duì)象省有,來持有它痒留,根據(jù)關(guān)聯(lián)時(shí)設(shè)定的內(nèi)存管理方式,管理它的生命周期蠢沿。
用于標(biāo)記關(guān)聯(lián)對(duì)象的key伸头,利用了靜態(tài)變量地址不變的原理,有三種寫法舷蟀,效果等同:
1恤磷、static void *strKey = &strKey;
2、static NSString *strKey = @"strKey";
3野宜、static char strKey
需要注意扫步,
1,關(guān)聯(lián)對(duì)象必須是對(duì)象,如果是基本類型匈子,需要包裝成對(duì)象類型河胎,再做關(guān)聯(lián),讀的時(shí)候再把對(duì)象類型轉(zhuǎn)換成基本類型虎敦。
2,每給對(duì)象關(guān)聯(lián)一個(gè)對(duì)象游岳,就要一個(gè)新的key。
3,關(guān)聯(lián)對(duì)象中的object原茅,可以是類對(duì)象吭历,也可以是實(shí)例對(duì)象。如果是類對(duì)象擂橘,則屬性關(guān)聯(lián)到了類上晌区,如果是實(shí)例對(duì)象,則屬性關(guān)聯(lián)到了實(shí)例上通贞。
關(guān)聯(lián)對(duì)象需要的接口:
void objc_setAssociatedObject(object, &key, anAssociatedObject, OBJC_ASSOCIATION_RETAIN);
id objc_getAssociatedObject(object, &key)
void objc_removeAssociatedObjects(anAssociatedObject)