關(guān)聯(lián)對(duì)象可以為category添加成員變量,因?yàn)槲覀冸m然可以通過(guò)category為類添加屬性,但是只是生成了方法聲明,并不能添加方法實(shí)現(xiàn)也不能生成成員變量(那還有個(gè)鳥用呢????);雖然我們可以手動(dòng)添加方法實(shí)現(xiàn),但是set方法和get 方法需要一個(gè)變量去存儲(chǔ)這個(gè)變量值,我們可以通過(guò)添加全局變量去存儲(chǔ)這個(gè)變量,但是存在多個(gè)對(duì)象公用一個(gè)全局變量的問(wèn)題。也可以創(chuàng)建一個(gè)字典全局變量,以對(duì)象的地址為key 也能一對(duì)一的存儲(chǔ)對(duì)象的屬性值。但是存在線程安全問(wèn)題。這個(gè)時(shí)候就可以使用關(guān)聯(lián)對(duì)象,Apple創(chuàng)建了一個(gè)全局對(duì)象AssociationsManager幫我們實(shí)現(xiàn)了更好的方式去管理這個(gè)變量去存儲(chǔ)我們新加的屬性值。
面試
- 關(guān)聯(lián)對(duì)象是線程安全的么?
- 關(guān)聯(lián)對(duì)象怎么釋放,對(duì)象釋放時(shí)怎么釋放關(guān)聯(lián)對(duì)象?
方式1:
const void * nameKey = &nameKey;
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
return objc_getAssociatedObject(self, nameKey);
}
弊端是外部通過(guò) extern const void * nameKey; 獲取這個(gè)值修改這個(gè)值。
方式2:
static const void * nameKey = &nameKey;
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
return objc_getAssociatedObject(self, nameKey);
}
static 修飾后保證只能在當(dāng)前文件中修改。
方式3:
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
// 隱式參數(shù)
// self , _cmd == @selector(name)
return objc_getAssociatedObject(self, _cmd);
}
關(guān)聯(lián)對(duì)象實(shí)際上是使用AssociationsManager這個(gè)全局變量的hashMap儲(chǔ)存在內(nèi)存中,并不是存儲(chǔ)在關(guān)聯(lián)對(duì)象的內(nèi)存中:
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation

面試參考答案
- 關(guān)聯(lián)對(duì)象是線程安全的么?
是線程安全的因?yàn)殛P(guān)聯(lián)對(duì)象的值是儲(chǔ)存在一個(gè)全局的AssociationsManager中的AssociationsHashMap hashMap表中,set和get都是以對(duì)象的地址為key計(jì)算出下標(biāo)值取出對(duì)應(yīng)的ObjectAssociationMap,再以void * 為key去ObjectAssociationMap這張hashMap表中取出ObjcAssociation,再取出_value。
- 關(guān)聯(lián)對(duì)象怎么釋放,對(duì)象釋放時(shí)怎么釋放關(guān)聯(lián)對(duì)象?
移除單個(gè)的關(guān)聯(lián)對(duì)象只需傳入nil會(huì)抹除ObjectAssociationMap中對(duì)應(yīng)的ObjcAssociation:
objc_setAssociatedObject(self, @selector(name), nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
跟隨對(duì)象釋放
isa指針中有has_assoc的一個(gè)位域,如果該位是1,說(shuō)明該對(duì)象有關(guān)聯(lián)對(duì)象。接下來(lái)會(huì)去AssociationsManager查找該對(duì)象的AssociationsHashMap,并從內(nèi)存中抹除。
- runtime在奇葩需求當(dāng)中的運(yùn)用(比如產(chǎn)品要求5和6上面顯示不同的字體大小,可以用runtime的交換方法
- Block中可以修改全局變量,全局靜態(tài)變量,局部靜態(tài)變量嗎?
未完待續(xù)。。。