iOS Category实现原理 (补充)

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调用。

原文地址:https://www.cnblogs.com/ShaoYinling/p/10239861.html

时间: 2024-10-12 14:55:54

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

iOS学习--UIScrollView 原理详解

iOS学习--UIScrollView 原理详解 http://blog.csdn.net/yanfangjin/article/details/7898189 ScrollView UIScrollView UIScrollView为了显示多于一个屏幕的内容或者超过你能放在内存中的内容. Scroll View为你处理缩小放大手势,UIScrollView实现了这些手势,并且替你处理对于它们的探测和回应.其中需要注意的子类是UITableView以及UITextView(用来显示大量的文字).

ios category类别的使用

ios category类别的使用 Objective-C提供了一个非常灵活的类(Class)扩展机制-类别(Category).类别用于对一个已经存在的类添加方法(Methods).你只需要知道这个类的公开接口,不需要知道类的源代码.需要注意的是,类别不能为已存在的类添加实例变量(Instance Variables). 类别的基本语法如下: @interface ClassName(CategoryName)//method declarations@end@interface 类名(类别名

iOS中多线程原理与runloop介绍

http://mobile.51cto.com/iphone-403490.htm iOS中多线程原理与runloop介绍 iPhone中的线程应用并不是无节制的,官方给出的资料显示iPhone OS下的主线程的堆栈大小是1M,第二个线程开始都是512KB.并且该值不能通过编译器开关或线程API函数来更改.只有主线程有直接修改UI的能力.……>>详细 兄弟专题:iOS人机交互指南之UI设计基础 1 iOS多线程编程知多少 在iOS的世界里有两种实现多线程的方式: 多线程是一个比较轻量级的方法来

iOS 应用签名原理&amp;重签名

在苹果的日常开发中,真机测试与打包等很多流程都会牵扯到各种证书,CertificateSigningRequest,p12等.但是很多相应的开发者并不理解iOS App应用签名的原理和流程.今天着重讲解一下此内容. 思考 在苹果的iOS系统出来之前,以前的主流程Mac OS/Window软件存在着安全隐患,盗版软件,病毒入侵等,苹果希望能解决类似的问题,保证每一个安装在苹果手机上的app都是经过苹果官方允许的,怎么保证呢? 一.iOS 应用签名原理 1 代码签名 要想回答上面“思考”的答案,首先

iOS - SDWebImage的原理以及使用流程

IOS框架研究之SDWebImage的原理以及使用流程 SDWebImage 这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. SDWebImage支持异步的图片下载+缓存,提供了 UIImageView+WebCacha 的 category,方便使用.SDWebImage加载图片的流程: 入口 setImageWithURL:placeholderImage:options: 会先把 placeholder

iOS开发-UI (一)补充 UIWindow UIView UIlabel

之前忘了把这些整理出来,现在补充一下,应该放在前面学习的 知识点: 1.UI的初步认识 2.UIWindow 3.UIView 4.UIlabel ======================== UI的初步认识 1.什么是UI(*) UI即User Interface(用户界面)的简称.UI设计则是指对软 件的人机交互.操作逻辑.界面美观的整体设计.好的UI设 计不仅是让软件变得有个性有品味,还要让软件的操作变得 舒适.简单.自由.充分体现软件的定位和特点. 2.第一个UI工程 1)UI工程的

iOS程序启动原理是什么

当刚开始学习ios开发的时候,我们学会做的第一件事就是创建一个新的项目.每次我都会好奇,为什么我们选择创建一个Single View Application项目的时候,什么代码都不用敲就可以在模拟器上运行程序了.要解答这个问题需要明白一点程序的启动原理,看完之后你就会明白. 首先,建立一个Single View Application项目以方便我们的研究.可以明确的是,不论是C语言还是Objiective-C语言程序,程序运行的入口都是main函数.所以我们从main函数开始入手. 创建新项目

iOS 多线程及其他补充

NSOperation NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 NSInvocationOperation 如果直接执行NSInvocationOperation中的操作, 那么默认会在主线程中执行 NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil]; [op1 start]; N

QF——iOS程序运行原理

iOS程序的运行原理: 1> main.m 主函数是所有程序的入口函数. 2> 在main函数里是UIApplicationMain函数,开启了一个无限循环,以监听该应用. 该UIApplicationMain函数有4个参数,前两个分别是main函数的参数,第3个参数UIApplication的类名,第4个是应用的代理类名. 2.1> 创建一个UIApplication实例,单例的,一个应用对应一个该对象,代表整个应用程序. 2.2> 再创建一个UIApplication的dele