iOS Category实现原理 (补充)

load 和 initialize

load

  1. load方法会在程序启动就会调用,当装载类信息的时候就会调用。

    • 调用顺序看一下源代码。在 objc-loadmethod.m 文件中实现
    void call_load_methods(void)
    {
    static bool loading = NO;
    bool more_categories; loadMethodLock.assertLocked(); // Re-entrant calls do nothing; the outermost call will finish the job.
    if (loading) return;
    loading = YES; void *pool = objc_autoreleasePoolPush(); do {
    // 1. Repeatedly call class +loads until there aren't any more
    // 1.调用类的 load 方法
    while (loadable_classes_used > 0) {
    call_class_loads();
    } // 2. Call category +loads ONCE
    // 2.调用分类的 load 方法
    more_categories = call_category_loads(); // 3. Run more +loads if there are classes OR more untried categories
    } while (loadable_classes_used > 0 || more_categories); objc_autoreleasePoolPop(pool); loading = NO;
    }
  2. 通过源码我们发现是优先调用类的load方法,之后调用分类的load方法。

  3. 查看load方法的调用源码,在 objc-loadmethod.m 文件中

static void call_class_loads(void)
{
int i; // Detach current loadable list.
struct loadable_class *classes = loadable_classes;
int used = loadable_classes_used;
loadable_classes = nil;
loadable_classes_allocated = 0;
loadable_classes_used = 0; // Call all +loads for the detached list.
for (i = 0; i < used; i++) {
Class cls = classes[i].cls;
load_method_t load_method = (load_method_t)classes[i].method;
if (!cls) continue; if (PrintLoading) {
_objc_inform("LOAD: +[%s load]\n", cls->nameForLogging());
}
(*load_method)(cls, SEL_load);
} // Destroy the detached list.
if (classes) free(classes);
}
  1. 我们看到load方法中直接拿到load方法的内存地址直接调用方法,不在是通过消息发送机制调用。
  2. 所以原始类的load方法并不会被覆盖,且调用类的load方法之前会保证其父类已经调用过load方法。

initialize

  1. 当类第一次接收到消息时,就会调用initialize,相当于第一次使用类的时候就会调用initialize方法。调用子类的initialize之前,会先保证调用父类的initialize方法。如果之前已经调用过initialize,就不会再调用initialize方法了。当分类重写initialize方法时会先调用分类的方法。

    • 看一下initialize的源码
    void callInitialize(Class cls)
    {
    ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);
    asm("");
    }
  2. 由此我们发现,initialize是通过消息发送机制调用的,消息发送机制通过isa指针找到对应的方法与实现,因此先找到分类方法中的实现,会优先调用分类方法中的实现。

总结

  1. Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗?

    • Category中有load方法,load方法在程序启动装载类信息的时候就会调用。load方法可以继承。调用子类的load方法之前,会先调用父类的load方法。
  2. load、initialize的区别,以及它们在category重写的时候的调用的次序。
  • 调用方式:

    • load是根据函数地址直接调用,initialize是通过objc_msgSend调用
  • 调用时刻:
    • load是runtime加载类、分类的时候调用(只会调用1次),
    • initialize是类第一次接收到消息的时候调用,每一个类只会initialize一次(父类的initialize方法可能会被调用多次)
  • 调用顺序:
    • 先调用类的load方法,先编译那个类,就先调用load。在调用load之前会先调用父类的load方法。分类中load方法不会覆盖本类的load方法,先编译的分类优先调用load方法。
    • initialize先初始化父类,之后再初始化子类。如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次),如果分类实现了+initialize,就覆盖类本身的+initialize调用。

iOS Category实现原理 (补充)的更多相关文章

  1. iOS Category实现原理

    iOS Category实现原理 实现原理 我们不主动引入 Category 的头文件,Category 中的方法都会被添加进主类中.我们可以通过 - performSelector: 等方式 对 C ...

  2. iOS Category 添加属性实现原理 - 关联对象

    iOS Category 添加属性实现原理 - 关联对象 RunTime为Category动态关联对象 使用RunTime给系统的类添加属性,首先需要了解对象与属性的关系.对象一开始初始化的时候其属性 ...

  3. 结合 category 工作原理分析 OC2.0 中的 runtime

    绝大多数 iOS 开发者在学习 runtime 时都阅读过 runtime.h 文件中的这段代码: struct objc_class { Class isa  OBJC_ISA_AVAILABILI ...

  4. ios category类别的使用

    ios category类别的使用 Objective-C提供了一个非常灵活的类(Class)扩展机制-类别(Category).类别用于对一个已经存在的类添加方法(Methods).你只需要知道这个 ...

  5. iOS程序启动原理---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  6. iOS应用启动原理图解 及ARC强弱引用

    iOS应用启动原理图解(红色箭头表示strong强引用,绿色箭头代表weak若引用) 只要将UI控件拖到Storyboard里控制器的大view上,Xcode会自动将这些控件以强引用的形式加入到sel ...

  7. iOS 应用签名原理&重签名

    在苹果的日常开发中,真机测试与打包等很多流程都会牵扯到各种证书,CertificateSigningRequest,p12等.但是很多相应的开发者并不理解iOS App应用签名的原理和流程.今天着重讲 ...

  8. iOS多线程编程原理及实践

    摘要:iOS开发中,开发者不仅要做好iOS的内存管理,而且如果你的iOS涉及多线程,那你也必须了解iOS编程中对多线程的限制,iOS主线程的堆栈大小为1M,其它线程均为512KB,且这个限制开发者是无 ...

  9. iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...

    本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...

随机推荐

  1. JavaScript-Tool-富文本:Simditor

    ylbtech-JavaScript-Tool-富文本:Simditor 1.返回顶部 1. 2. 2.返回顶部 1. Simditor 是团队协作工具 Tower 使用的富文本编辑器. 相比传统的编 ...

  2. 开发板启动时,内核打印出"can't access tty,job control turned off"

    启动后的最后一行提示can't access tty,job control turned off, 这说明没有进入到控制台,原因就在于文件系统的/etc/inittab 这个文件里有问题 vi /e ...

  3. [转载]Doxygen C++ 注释风格

    转载自:http://luchenqun.com/?p=761 做一个C++方面的符合Doxygen的注释文档,备用. 1.头文件根原文件注释.这个我也不知道需要注释什么.能想到的是:谁写的,里面有些 ...

  4. 【Data Structure & Algorithm】字符串全排列

    字符串全排列 题目:输入一个字符串,打印出该字符串的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab.cba. 分析:考察对递归的理 ...

  5. UVaLive 3983 Robotruck (DP + 单调队列)

    题意:有n个垃圾,第i个垃圾坐标为(xi,yi),重量为wi,有一个机器人,要按照编号从小到大的顺序剑气所有的垃圾兵扔进垃圾桶,垃圾桶在原点, 每次总重量不能超过C,两点间距离为曼哈顿距离,求出最短的 ...

  6. java 中判断字符串相等

    今天写Java代码时遇到一个问题,就是关于判断两个字符串是否相等的问题.(刚尝试用SSH框架) 在大多编程中,通常比较两个字符串是否相同的表达式是“==”,但在java中不能这么写.在java中,用的 ...

  7. E20180525-hm

    sensitive adj. 敏感的; 感觉的; [仪] 灵敏的; 易受影响的; lookup v. 查找; 查表; speedy  adj. 快的,迅速的; 敏捷的 marshal  vt. 整理, ...

  8. CSS小技巧收藏

    居中对齐 很多时候我们需要把一个元素在其父级容器里水平.垂直居中对齐.以下我列出了常用的几种方法: 1.在知道子元素宽度与高度的情况下进行居中,采用位置定位:absolute + margin .pa ...

  9. 求N!的长度【数学】

    转自:http://blog.csdn.net/fengdian29147001/article/details/11992755 给一个数X,len=log10(X)+1就是X这个数的长度 ①:当N ...

  10. Puppet2d及教程

    http://www.jianshu.com/p/e56c7f5e58ab manual http://www.unitymanual.com/thread-35754-1-1.html http:/ ...