iOS 面試題(五):weak 的內部實現原理 --轉自唐巧


問題

weak 變量在引用計數為0時,會被自動設置成 nil,這個特性是如何實現的?

答案

在 Friday QA 上,有一期專門介紹 weak 的實現原理。https://mikeash.com/pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html

《Objective-C高級編程》一書中也介紹了相關的內容。

簡單來說,系統有一個全局的 CFMutableDictionary 實例,來保存每個對象的 weak 指針列表,因為每個對象可能有多個 weak 指針,所以這個實例的值是 CFMutableSet 類型。

剩下我們要做的,就是在引用計數變成 0 的時候,去這個全局的字典里面,找到所有的 weak 指針,將其值設置成 nil。如何做到這一點呢?Friday QA 上介紹了一種類似 KVO 實現的方式。當對象存在 weak 指針時,我們可以將這個實例指向一個新創建的子類,然后修改這個子類的 release 方法,在 release 方法中,去從全局的 CFMutableDictionary 字典中找到所有的 weak 對象,並且設置成 nil。我摘抄了 Friday QA 上的實現的核心代碼,如下:

Class subclass = objc_allocateClassPair(class, newNameC, 0);
Method release = class_getInstanceMethod(class, @selector(release));
Method dealloc = class_getInstanceMethod(class, @selector(dealloc));
class_addMethod(subclass, @selector(release), (IMP)CustomSubclassRelease, method_getTypeEncoding(release));
class_addMethod(subclass, @selector(dealloc), (IMP)CustomSubclassDealloc, method_getTypeEncoding(dealloc));
objc_registerClassPair(subclass);

 

當然,這並不代表蘋果官方是這么實現的,因為蘋果的這部分代碼並沒有開源。《Objective-C高級編程》一書中介紹了 GNUStep 項目中的開源代碼,思想也是類似的。所以我認為雖然實現細節會有差異,但是大致的實現思路應該差別不大。

全文完。


下一期的面試題:

我們知道,從 Storyboard 往編譯器拖出來的 UI 控件的屬性是 weak 的,如下所示:

@property (weak, nonatomic) 
    IBOutlet UIButton *myButton;

 

那么,如果有一些 UI 控件我們要用代碼的方式來創建,那么它應該用 weak 還是 strong 呢?為什么?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM