I am trying to do some runtime programmation on Objective-C. In order to do this I override the resolveClassMethod method.
Unfortunately I come up with some compilation error with clang when ARC is active :
error: no known class method for selector 'dynamic'
Everything works fine if I use gcc or clang without ARC (-fno-objc-arc option passed), except a warning instead of the error.
I am aware that ARC need to know the name of the method called to figure out how to manage the memory with returned value (following method name convention). But how to this issue without an ugly performSelector call instead of a direct method call ?
Here is my code :
Test.m
#import "Test.h"
#import <objc/runtime.h>
NSString* dynamicImp(id slef, SEL _cmd)
{
NSLog(@"Dynamic method called");
return @"dynamicImp";
}
@implementation Test
- (NSString*)name
{
return @"John";
}
+ (BOOL)resolveClassMethod:(SEL)name
{
if (name == @selector(dynamic))
{
Class metaClass = objc_getMetaClass([NSStringFromClass([self class]) UTF8String]);
class_addMethod(metaClass, name, (IMP) dynamicImp, "@@:");
return YES;
}
return NO;
}
+ (IMP)methodForSelector:(SEL)aSelector
{
if (aSelector == @selector(dynamic))
{
return (IMP) dynamicImp;
}
else
{
return [super methodForSelector:aSelector];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
if (aSelector == @selector(dynamic))
{
return YES;
}
else
{
return [NSObject respondsToSelector:aSelector];
}
}
@end
Test.h
#import <Cocoa/Cocoa.h>
@interface Test : NSObject <NSObject> {
NSString *_name;
}
- (NSString*)name;
@end
main.m
#import <Cocoa/Cocoa.h>
#import <stdio.h>
#import "Test.h"
int main(int argc, char* argv[])
{
@autoreleasepool {
Test *test = [[Test alloc] init];
NSLog(@"Hello, %@", [test name]);
NSLog(@"How are you , %@", [Test dynamic]);
}
return 0;
}
Gcc or clang without ARC
Compilation result
main.m:13:36: warning: class method '+dynamic' not found (return type defaults to 'id')
NSLog(@"How are you , %@", [Test dynamic]);
Output
2012-10-22 10:33:15.563 test-clang[957:707] Hello, John 2012-10-22
2012-10-22 10:33:15.565 test-clang[957:707] Dynamic method called 2012-10-22
2012-10-22 10:33:15.565 test-clang[957:707] How are you , dynamicImp
Clang with ARC
Compilation result
main.m:13:36: error: no known class method for selector 'dynamic'
NSLog(@"How are you , %@", [Test dynamic]);
PS : I didn't care for the moment on memory management as my goal is to compile this code with ARC activated.