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

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