李岡諭*_*李岡諭 9 objective-c objective-c-runtime
当我使用objc运行时函数class_addMethod()向NSObject的实例选择器注入一个实现时,它实际上将实现注入实例选择器和类选择器:
@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);
Run Code Online (Sandbox Code Playgroud)
现在我们只声明helloWorldvia Objc Category 的接口,并将helloWorld消息调用到NSObject实例和类:
// 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];
Run Code Online (Sandbox Code Playgroud)
虽然您只是将helloWorld实现注入到NSObject实例选择器中class_addMethod(),但是在注入之后解析了类和实例消息:
=> 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
Run Code Online (Sandbox Code Playgroud)
经过测试,我发现class_addMethod()只有当目标类为class_addMethod()is 时才将实现添加到类和实例选择器中NSObject.
它是objc-runtime还是Cocoa的bug?
不,这不是一个bug.它定义了运行时系统(虽然模糊不清)的行为.
就像每个实例都有一个isa指向它的类的实例变量一样,内存中的每个类结构都有一个isa指向其元类的成员.就像任何给定的类包含有关其实例的元数据一样 - 包括实例响应的方法列表 - 类的元类包含有关类本身的元数据,包括类响应的方法列表.
此外,每个类结构都有一个superclass指向其超类的成员,该成员在元类层次结构中镜像(即,每个元类superclass是另一个元类).
但是有一个主要的区别:NSObjectis 的超类是nil,而NSObject元类的超类是NSObject.换句话说,NSObject's元类继承了NSObject实例方法.因此,Objective-C类不仅响应其定义的类方法,还响应NSObject实例方法.
困惑了吗?Greg Parker撰写了一篇精彩的博客,其中包含一个非常有用的图表,说明了如何将它们连接在一起:
编辑
唉,互联网.如果您当前使用的浏览器不显示内嵌PDF文档,则此处是直接指向图表的链接:
| 归档时间: |
|
| 查看次数: |
2565 次 |
| 最近记录: |