iOS開發之 runtime(31) :關於 weak-linked class

本系列博客是本人的源碼閱讀筆記,如果有 iOS 開發者在看 runtime 的,歡迎大家多多交流。爲了方便討論,本人新建了一個微信羣(iOS技術討論羣),想要加入的,請添加本人微信:zhujinhui207407,【加我前請備註:ios 】,本人博客http://www.kyson.cn 也在不停的更新中,歡迎一起討論

本文完整版詳見筆者小專欄:https://xiaozhuanlan.com/runtime

前言

上一篇文章我們說到添加 remap class 的兩個前提條件是 missingWeakSuperclass 或者 popFutureNamedClass 存在。今天我們詳細分析一下,什麼是 missingWeakSuperclass。

分析

missingWeakSuperclass 的源碼爲:

/***********************************************************************
* missingWeakSuperclass
* Return YES if some superclass of cls was weak-linked and is missing.
**********************************************************************/
static bool  missingWeakSuperclass(Class cls) {
    assert(!cls->isRealized());

    if (!cls->superclass) {
        // superclass nil. This is normal for root classes only.
        return (!(cls->data()->flags & RO_ROOT));
    } else {
        // superclass not nil. Check if a higher superclass is missing.
        Class supercls = remapClass(cls->superclass);
        assert(cls != cls->superclass);
        assert(cls != supercls);
        if (!supercls) return YES;
        if (supercls->isRealized()) return NO;
        return missingWeakSuperclass(supercls);
    }
}

代碼的註釋已經一目瞭然:該函數就是判斷某個 class 的父類是否是 weak-linked 並且缺失了。那 什麼叫做 weak-linked?比如 NSObject 是否是 weak-linbked ?很顯然不是的。那麼什麼是 weak-linked?

weak-linked
我們開發的時候,都會使用最新的SDK,但是爲了讓老的設備可以下載並運行我們的應用,就要將Deployment Target設置成之前系統的版本號。例如我們應用使用iOS 8.1的SDK,Deployment Target設置成iOS 5.1.1,雖然我們開發的時候使用的是8.1的SDK,但是程序運行在的設備中卻可能是6.0 or 7.0的SDK上,按照蘋果的說法,如果我們應用使用了最新SDK引入的特性,比如符號、函數等,那麼在版本較舊的設備上就運行不了。下面是蘋果官方文檔的一段話:
Normally, if an application uses a new feature in a framework, it is unable to run on earlier versions of the framework that do not support that feature. Such applications would either fail to launch or crash when an attempt to use the feature was made.
那麼爲什麼我們使用最新的SDK開發的應用卻可以運行在舊的系統中呢?答案是使用了弱引用。資料裏面說過,我們自己創建的framework,如果需要做版本兼容,那麼就要對今後加入的符號等使用弱引用,使用了弱引用之後,即使在版本較舊的環境下跑,也可以運行,只是相應的符號是NULL,下面就是教我們怎樣定義弱引用。有一點需要說明的是,如果一個framework沒有爲新加入的符號加入弱引用,那也不必擔心,我們只要在鏈接時弱引用整個framework就好,方法就是鏈接的時候使用 -weak_framework frameworkName

// weak link the function
extern int MyFunction() __attribute__((weak_import));
// weak link the variable
extern int MyVariable __attribute__((weak_import));

這麼一來, missingWeakSuperclass 的作用的作用就不言而喻了:查看 cls 類的祖宗類中是否有類是 weak-linked 的,並且已經 missing,祖宗類裏有 missing weak-linked 的,則 cls 的所有信息也是不可信的,所以將其添加到重映射表裏,映射爲nil,即 cls -> nil。

總結

本文講解了 weak-linked class 的概念以及 missingWeakSuperclass 的作用,希望對大家有所幫助。

參考

Weakly linked symbols and frameworks(弱引用符號和framework)

Frameworks and Weak Linking

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章