Obj-C用起来真是各种happy,比如现在有这样一种情况:有一个类,我们希望它能响应一个消息(message),但是这个类没有相应的方法(method),而你又偏偏不能重写/继承这个类。这时我们可能会想到,能不能动态地给类添加一个方法呢?感谢Obj-C,仅需简单几步就能实现。
先看一段代码
#if TARGET_IPHONE_SIMULATOR #import #else #import #import #endif @interface EmptyClass:NSObject @end @implementation EmptyClass @end void sayHello(id self, SEL _cmd) { NSLog(@"Hello"); } - (void)addMethod { class_addMethod([EmptyClass class], @selector(sayHello2), (IMP)sayHello, "v@:"); // Test Method EmptyClass *instance = [[EmptyClass alloc] init]; [instance sayHello2]; [instance release]; }
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
参数说明:
cls:被添加方法的类
name:可以理解为方法名,这个貌似随便起名,比如我们这里叫sayHello2
imp:实现这个方法的函数
types:一个定义该函数返回值类型和参数类型的字符串,这个具体会在后面讲
接着创建EmptyClass的实例,调用sayHello2,运行,输出Hello,添加方法成功。
接下来说一下types参数,
比如我们要添加一个这样的方法:-(int)say:(NSString *)str;
相应的实现函数就应该是这样:
int say(id self, SEL _cmd, NSString *str) { NSLog(@"%@", str); return 100;//随便返回个值 }
class_addMethod这句就应该这么写:
1 |
class_addMethod([EmptyClass class], @selector(say:), (IMP)say, "i@:@"); |
其中types参数为"i@:@“,按顺序分别表示:
i:返回值类型int,若是v则表示void
@:参数id(self)
::SEL(_cmd)
@:id(str)
这些表示方法都是定义好的(Type Encodings),关于Type Encodings的其他类型定义请参考官方文档
最后调用say:方法:
int a = [instance say:@"something"]; NSLog(@"%d", a); |
输出something和100。
关于本文所涉及内容的详细信息请参考Objective-C Runtime Reference
本文参考了: