iOS底层探索:经典案例分析

283 阅读3分钟

注:本文旨在记录笔者的学习过程,仅代表笔者个人的理解,如果有表述不准确的地方,欢迎各位指正!因为涉及到的概念来源自网络,所以如有侵权,也望告知!

前言

本文主要通过实际案例了解iOS底层实现。

正文

1、class_getInstanceMethod与class_getClassMethod

案例代码:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        LGPerson *person = [LGPerson alloc];
        Class pClass     = object_getClass(person);
        lgInstanceMethod_classToMetaclass(pClass);
        lgClassMethod_classToMetaclass(pClass);
    }
    return 0;
}

void lgInstanceMethod_classToMetaclass(Class pClass){

    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);

    Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
    Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));

    Method method3 = class_getInstanceMethod(pClass, @selector(sayGoodBye));
    Method method4 = class_getInstanceMethod(metaClass, @selector(sayGoodBye));

    LGLog(@"%s - %p-%p-%p-%p",__func__,method1,method2,method3,method4);
}

void lgClassMethod_classToMetaclass(Class pClass){

    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);

    Method method1 = class_getClassMethod(pClass, @selector(sayHello));
    Method method2 = class_getClassMethod(metaClass, @selector(sayHello));

    Method method3 = class_getClassMethod(pClass, @selector(sayGoodBye));
    // 元类 为什么有 sayGoodBye 类方法 0 1
    //
    Method method4 = class_getClassMethod(metaClass, @selector(sayGoodBye));

    LGLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);
}

控制台结果打印:

OC源码如下:

结合之前文章——iOS底层探索:isa走向及类结构探索中提及到的的isa走位图,可知实例方法是存储在类中的,类方法是存储在元类中的,所以:

  • class_getClassMethod查找过程:传入类(元类-->根元类 --> 根类 --> nil )是否能查找到对应的方法。
  • class_getInstanceMethod查找过程:传入类(当前类--> 根类 --> nil )是否能查找到对应的方法。

分析:

lgInstanceMethod_classToMetaclass中:

  • method1:LGPerson类中找到- (void)sayHello;
  • method2:LGPerson元类中不能找到- (void)sayHello;
  • method3:LGPerson类中不能找到+ (void)sayGoodBye;
  • method4:LGPerson元类中找到+ (void)sayGoodBye;

lgClassMethod_classToMetaclass中:

  • method1:LGPerson元类中不能找到- (void)sayHello;
  • method2:LGPerson元类中不能找到- (void)sayHello;
  • method3:LGPerson元类中找到+ (void)sayGoodBye;
  • method4:LGPerson元类中找到+ (void)sayGoodBye;

2、isKindOfClass与isMemberOfClass

案例代码:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
        BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
        BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];
        BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];
        NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);

        BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
        BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
        BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
        BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];
        NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
    }
    return 0;
}

控制台结果打印:

OC源码如下:

结合之前文章——iOS底层探索:isa走向及类结构探索中提及到的的isa走位图,可知:

  • + (BOOL)isKindOfClass:(Class)cls;比对流程:传入类 VS 调用类(

    元类 --> 根元类 --> 根类 --> nil )。

  • - (BOOL)isKindOfClass:(Class)cls;比对流程:传入类 VS 调用对象 对象的类 --> 父类 --> 根类 --> nil )。

  • + (BOOL)isMemberOfClass;比对流程:传入类 VS 调用类的元类

  • - (BOOL)isMemberOfClass:(Class)cls;比对流程:传入类 VS 调用对象的类

案例分析:

  • re1:NSObject类 VS NSObject元类-->NSObject类 ,比对两次后返回相等
  • re2:NSObject类 VS NSObject元类,比对一次后返回不相等。
  • re3:LGPerson VS LGPerson元类-->NSObject元类-->NSObject类--> nil,比对四次后返回相等
  • re4:LGPerson类 VS LGPerson元类,比对一次后返回不相等。
  • re5:NSObject类 VS NSObject类,比对一次后返回相等
  • re6:NSObject类 VS NSObject类,比对一次后返回相等
  • re7:LGPerson类 VS LGPerson类,比对一次后返回相等
  • re8:LGPerson类 VS LGPerson类,比对一次后返回相等