题目描述
下面的代码运行的结果是什么? 崩溃 还是 打印?
@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
疑问
- 在没有实现 + foo方法时,为什么 + foo方法的IMP 会变成 - foo方法的IMP?
- 实现了 + foo方法后,为什么 + foo 方法的IMP 却没有变成 - foo方法的IMP?编译器到底是怎么关联类方法的SEL和IMP?
结语
希望研究过这块的朋友能告诉我这些细节的资料在哪里? 提前感谢 。
如图,所有元类的isa指针都指向 NSObject 的元类,NSObjct元类 的 superClass 指向NSObject 自身。
题目中,category 分别将 +foo 和 -foo 添加到 NSObject元类 和 NSObject 类对象中,形成类方法与实例方法。
[[NSObject new] foo] 在 NSObject 类对象中找到 -foo 并执行;
[NSObject foo] 在 NSObject元类中找 +foo 方法,没有找到,再去 superClass 中找,也就是去 NSObject 类对象中找 +foo 方法;而我们知道,OC中的方法都是通过字符串匹配的,所以最终匹配到的是同名的 -foo 方法,然后执行。