When I use objc runtime function class_addMethod()
to inject an implementation to NSObject's instance selector, it actually inject the implementation to the instance selector AND the class selector:
@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);
Now we just declare the interface of helloWorld
via Objc Category, and invoke the helloWorld
message to both NSObject
instance and class:
// 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];
Although you just injected the helloWorld
implementation to the NSObject instance selector via class_addMethod()
, but both class and instance messages are resolved after injection:
=> 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
After testing, I found that class_addMethod()
adds the implementation to both class and instance selectors only when the target class of class_addMethod()
is NSObject
.
Is it a bug for objc-runtime or Cocoa?