美文网首页ios面试题
iOS Cateogry的深入理解&&initialize方法调

iOS Cateogry的深入理解&&initialize方法调

作者: 枫紫_6174 | 来源:发表于2020-12-04 15:33 被阅读0次
    • 上一篇文章我们讲到了load方法,今天我们来看看initialize

    新建项目,新建类(和上一篇文章所建的类相同,方便大家理解,具体的类相关关系可以看上一篇文章我的介绍)类结构图如下

    相关类
    • 将原来的load方法换成initialize


      TCPerson
      TCPerson (TCtest1)
      TCPerson (TCTest2)

    先告诉大家initialize方法调用的时间,以便大家带着答案去理解initialize:在类第一次接收到消息的时候调用,它区别于load(运行时加载类的时候调用),下面我们来深入理解initialize

      1. 相信大家在想什么叫第一次接收消息了,我们回到main()


        main

        运行程序,输出结果:


        输出结果

    说明:NSLog(@"---")是由于我建的是命令行工程,不写这个,貌似不能显示控制台,Xcode版本是12,当然你们的要显示控制台,直接去掉这行代码

    从输出结果可以看到没有任何关于initialize的打印,程序直接退出

    • 2.initialize的打印
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            [TCPerson alloc];
        }
        return 0;
    }
    

    运行结果:

    2020-12-04 14:59:17.417072+0800 TCCateogry[1616:79391] TCPerson (TCtest2) +initialize
    Program ended with exit code: 0
    

    从上面的输出结果我们可以看到,TCPerson (TCtest2) +initialize打印

    load是直接函数指针直接调用,类,分类,继承等等

    [TCPerson alloc]就是相当于该类发送消息,但是它只会调用类,分类的其中一个(取决于编译顺序,从输出结果可以看出,initialize走的是objc_msgSend,而load直接通过函数指针直接调用,所以initialize通过isa方法查找调用,isa方法查找可参考iOS 实例对象,类对象,元类对象的关联---isa/superclass指针(2)

    多次向TCPerson发送消息的输出结果

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            [TCPerson alloc];
            [TCPerson alloc];
            [TCPerson alloc];
            [TCPerson alloc];
        }
        return 0;
    }
    

    输出结果:

    2020-12-04 15:11:12.246442+0800 TCCateogry[1659:85317] TCPerson (TCtest2) +initialize
    Program ended with exit code: 0
    

    initialize只会调用一次

    我们再来看看继承关系中,initialize的调用

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            [TCStudent alloc];
          
        }
        return 0;
    }
    

    输出结果:

    2020-12-04 15:14:58.705423+0800 TCCateogry[1705:87507] TCPerson (TCtest2) +initialize
    2020-12-04 15:14:58.705750+0800 TCCateogry[1705:87507] TCStudent (TCStudentTest2) +initialize
    Program ended with exit code: 0
    

    从输出结果来看,子类调用initialize之前,会先调用父类的initialize,再调用自己的initialize,当然无论父类调用initialize,还是子类调用initialize,如果有多个分类(这里指的是父类调用父类的分类,子类调用子类的分类),调用initialize取决于分类的编译顺序(调用后编译分类中的initialize,类似于压栈,先进后出),值得注意的是,无论父类子类的initialize,都只调用一次

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            [TCPerson alloc];
            [TCPerson alloc];
            [TCStudent alloc];
            [TCStudent alloc];
        }
        return 0;
    }
    

    输出结果:

    020-12-04 15:23:27.168243+0800 TCCateogry[1731:91248] TCPerson (TCtest2) +initialize
    2020-12-04 15:23:27.168601+0800 TCCateogry[1731:91248] TCStudent (TCStudentTest2) +initialize
    Program ended with exit code: 0
    

    如果子类(子类的分类也不实现)不实现initialize,则父类的initialize就调用多次

    #import "TCStudent.h"
    
    @implementation TCStudent
    //+ (void)initialize{
    //    NSLog(@"TCStudent +initialize");
    //}
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            [TCPerson alloc];   
            [TCStudent alloc];
        }
        return 0;
    }
    
    

    输出结果:

    2020-12-04 15:37:09.055459+0800 TCCateogry[1822:98237] TCPerson (TCtest2) +initialize
    2020-12-04 15:37:09.055775+0800 TCCateogry[1822:98237] TCPerson (TCtest2) +initialize
    Program ended with exit code: 0
    

    如果子类(子类的分类实现initialize)不实现initialize,则子类的initialize不会调用,调用子类分类的initialize(当然多个分类的话,调用哪个的initialize取决于编译顺序)

    #import "TCStudent.h"
    
    @implementation TCStudent
    + (void)initialize{
        NSLog(@"TCStudent +initialize");
    }
    @end
    #import "TCStudent+TCStudentTest1.h"
    
    @implementation TCStudent (TCStudentTest1)
    + (void)initialize{
        NSLog(@"TCStudent (TCStudentTest1) +initialize");
    }
    @end#import "TCStudent+TCStudentTest2.h"
    
    @implementation TCStudent (TCStudentTest2)
    + (void)initialize{
        NSLog(@"TCStudent (TCStudentTest2) +initialize");
    }
    @end
    

    输出结果:

    2020-12-04 15:41:21.863260+0800 TCCateogry[1868:100750] TCPerson (TCtest2) +initialize
    2020-12-04 15:41:21.863568+0800 TCCateogry[1868:100750] TCStudent (TCStudentTest2) +initialize
    Program ended with exit code: 0
    

    相关文章

      网友评论

        本文标题:iOS Cateogry的深入理解&&initialize方法调

        本文链接:https://www.haomeiwen.com/subject/wcqiwktx.html