当我使用 objc 运行时函数 class_addMethod()
将实现注入(inject)到 NSObject 的实例选择器时,它实际上将实现注入(inject)到实例选择器 AND 类选择器:
@implementation HelloWorldClass
- (void) helloWorld{
NSLog(@"hello world from instance method -helloWorld");
}
@end
// ====
// Do method injection when the application did finish launching.
Class sourceClass = objc_getClass("HelloWorldClass");
Class targetClass = objc_getClass("NSObject");
SEL helloWorldSelector = @selector(helloWorld);
Method method = class_getInstanceMethod(sourceClass, helloWorldSelector);
IMP imp = method_getImplementation(method);
const char *methodTypeEncoding = method_getTypeEncoding(method);
class_addMethod(targetClass, helloWorldSelector, imp, methodTypeEncoding);
现在我们只需通过 Objc Category 声明 helloWorld
的接口(interface),并向 NSObject
实例和类调用 helloWorld
消息:
// Declare the interface for `helloWorld
@interface NSObject (HelloWorld)
+ (void) helloWorld;
- (void) helloWorld;
@end
// Send the `helloWorld` message to NSObject class
NSLog(@"Send the `helloWorld` message to NSObject class");
[NSObject helloWorld];
// Send the `helloWorld` message to NSObject instance
NSLog(@"Send the `helloWorld` message to NSObject instance");
[[NSObject new] helloWorld];
虽然你只是通过 class_addMethod()
将 helloWorld
实现注入(inject)到 NSObject 实例选择器中,但是注入(inject)后类和实例消息都被解析了:
=> Send the `helloWorld` message to NSObject class
=> hello world from instance method -helloWorld
=> Send the `helloWorld` message to NSObject instance
=> hello world from instance method -helloWorld
经过测试,我发现只有当class_addMethod()
的目标类是NSObject<时,
。 class_addMethod()
才会将实现同时添加到类选择器和实例选择器中
它是 objc-runtime 还是 Cocoa 的错误?
最佳答案
不,这不是错误。它是运行时系统的已定义(虽然晦涩)行为。
正如每个实例都有一个指向它的类的isa
实例变量一样,内存中的每个类结构都有一个isa
成员指向它的元类。正如任何给定的类都包含有关其实例的元数据——包括实例响应的方法列表——类的元类包含有关类本身的元数据,包括类响应的方法列表到。
此外,每个类结构都有一个指向其父类(super class)的superclass
成员,它反射(reflect)在元类层次结构中(即,每个元类的superclass
是另一个元类) .
不过有一个主要区别:NSObject
的父类(super class)是 nil
,而 NSObject
元类的父类(super class)是 NSObject
。也就是说,NSObject
的元类继承了NSObject
的实例方法。因此,Objective-C 类不仅响应它们定义的类方法,它们还响应 NSObject
实例方法。
还在迷茫吗? Greg Parker 写了一篇很棒的博客,其中包含一个非常有用的图表,说明了这一切是如何连接在一起的:
Hamster Emporium archive - Classes and metaclasses
编辑
唉,互联网。如果您当前使用的浏览器不显示内联 PDF 文档,这里有一个直接指向图表的链接:
关于objective-c - 为什么 objc 运行时函数 `class_addMethod()` 在目标类为 `NSObject` 时将实现添加为实例和类方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20300924/