一道iOS面试题,关乎OC是如何寻找类方法实现的细节

好有魔力
  • 0
新手上路,请多包涵

题目描述

下面的代码运行的结果是什么? 崩溃 还是 打印?

@interface NSObject(Test)

+ (void)foo;
- (void)foo;

@end

@implementation NSObject(Test)

//+ (void)foo {
//    NSLog(@"+ foo");
//}

- (void)foo {
    NSLog(@"- foo");
}

@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        [NSObject foo];
        [[NSObject new] foo];
    }
    return 0;
}

测试结果

测试结果是可以运行的,结果如下:

2020-07-22 11:14:10.938981+0800 Test[3689:80562] - foo
2020-07-22 11:14:10.939060+0800 Test[3689:80562] - foo

我又实现了 + foo 方法,进行了测试,结果如下:

2020-07-22 11:15:40.686320+0800 Test[3712:81812] + foo
2020-07-22 11:15:40.686375+0800 Test[3712:81812] - foo

疑问

  1. 在没有实现 + foo方法时,为什么 + foo方法的IMP 会变成 - foo方法的IMP?
  2. 实现了 + foo方法后,为什么 + foo 方法的IMP 却没有变成 - foo方法的IMP?编译器到底是怎么关联类方法的SEL和IMP?

结语

希望研究过这块的朋友能告诉我这些细节的资料在哪里? 提前感谢 。

回复
阅读 715
1 个回答

isa 与 superClass

如图,所有元类的isa指针都指向 NSObject 的元类,NSObjct元类 的 superClass 指向NSObject 自身。
题目中,category 分别将 +foo 和 -foo 添加到 NSObject元类 和 NSObject 类对象中,形成类方法与实例方法。
[[NSObject new] foo] 在 NSObject 类对象中找到 -foo 并执行;
[NSObject foo] 在 NSObject元类中找 +foo 方法,没有找到,再去 superClass 中找,也就是去 NSObject 类对象中找 +foo 方法;而我们知道,OC中的方法都是通过字符串匹配的,所以最终匹配到的是同名的 -foo 方法,然后执行。

你知道吗?

宣传栏