要實現(xiàn) weak 屬性,首先要搞清楚 weak 屬性的特點:
weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系” (nonowning relationship)。為這種屬性設(shè)置新值時,設(shè)置方法既不保留新值,也不釋放舊值。此特質(zhì)同 assign 類似, 然而在屬性所指的對象遭到摧毀時,屬性值也會清空(nil out)。
那么 runtime 如何實現(xiàn) weak 變量的自動置nil?
runtime 對注冊的類, 會進行布局,對于 weak 對象會放入一個 hash 表中。 用 weak 指向的對象內(nèi)存地址作為 key,當(dāng)此對象的引用計數(shù)為0的時候會 dealloc,假如 weak 指向的對象內(nèi)存地址是a,那么就會以a為鍵, 在這個 weak 表中搜索,找到所有以a為鍵的 weak 對象,從而設(shè)置為 nil。
對象的內(nèi)存銷毀時間表,分四個步驟:
- 調(diào)用 -release :引用計數(shù)變?yōu)榱?/li>
- 對象正在被銷毀,生命周期即將結(jié)束.
- 不能再有新的 __weak 弱引用, 否則將指向 nil.
- 調(diào)用 [self dealloc]
- 子類 調(diào)用 -dealloc
- 繼承關(guān)系中最底層的子類 在調(diào)用 -dealloc
- 如果是 MRC 代碼 則會手動釋放實例變量們(iVars)
- 繼承關(guān)系中每一層的父類 都在調(diào)用 -dealloc
- NSObject 調(diào) -dealloc
- 只做一件事:調(diào)用 Objective-C runtime 中的
- object_dispose() 方法
- 調(diào)用 object_dispose()
- 為 C++ 的實例變量們(iVars)調(diào)用 destructors
- 為 ARC 狀態(tài)下的 實例變量們(iVars) 調(diào)用 -release
- 解除所有使用 runtime Associate方法關(guān)聯(lián)的對象
- 解除所有 __weak 引用
- 調(diào)用 free()
驗證:
生成weak屬性的對象, 并指向一個對象,當(dāng)對象銷毀之后,指向該對象的weak屬性的對象也會隨之銷毀。
__weak id weakObj1 = nil;
__weak id weakObj2 = nil;
{
id obj = [[NSObject alloc] init]; // 引用計數(shù)會增加,這里不會是weak的
weakObj1 = obj;
weakObj2 = obj;
NSLog(@"obj: %@", obj);
NSLog(@"weakObj1: %@", weakObj1);
NSLog(@"weakObj2: %@", weakObj2);
}
NSLog(@"weakObj1: %@", weakObj1);
NSLog(@"weakObj2: %@", weakObj2);
輸出為:
obj: <NSObject: 0x60800000bdc0>
weakObj1: <NSObject: 0x60800000bdc0>
weakObj2: <NSObject: 0x60800000bdc0>
weakObj1: (null)
weakObj2: (null)
因為 weak 本身是非擁有的,所有如果是把weakObj1設(shè)置為nil的話,是不會對其他的造成影響的。
參考:<a >吵了個吵 - iOS面試題</a>