您的位置:首页 > 其它

OC Rumtime—IMP的函数调用

2015-10-08 16:17 330 查看
最近在学习OC 运行时(runtime),测试了一个函数class_replaceMethod,具体如下:

IMP originalMethod;
NSString *CustomUppercaseString(id SELF,SEL _CMD){
NSLog(@"BeginConverting。。。");
NSString *result=originalMethod(SELF,_CMD);
NSLog(@"EndConverting。。。");
return result;
}
Implementation中:
- (void)runtimeTest{
originalMethod=[NSString instanceMethodForSelector:@selector(uppercaseString)];
class_replaceMethod([NSString class], @selector(uppercaseString), (IMP)MyUppercaseString,NULL);
NSString *s=@"zhang lei";
NSLog(@"uppercase:%@",[s uppercaseString]);
}
运行过程中在下面这行报错:
NSString *result=originalMethod(SELF,_CMD);
①先是提示参数太多,问百度说是IMP本身包含了self和_cmd俩参数,不用再显示传参。去掉参数后继续报错。

②提示在ARC下无法将void *转换为id。关闭ARC后依旧出错,还是无法转换。
当我查看IMP的定义时发现了这个:

/// A pointer to the function of a method implementation.
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ );
#else
typedef id (*IMP)(id, SEL, ...);
#endif
报错的主要原因是因为IMP取的是if中的定义,返回void *,于是怀疑项目编译设置上设置的不对。继续搜百度找到如下内容:“使用XCode6.X的小伙伴们要特别注意了,需要先到项目的构建设置里面把Apple LLVM 6.0 - PreprocessingEnable Strict Checking of objc_msgSend Calls 选项设置为NO,否则result = imp(clazz, sel);会报错的!!”(http://www.ithao123.cn/content-450798.html)于是按照上面说的进行了设置,运行成功。并且经过调试,发现确实是Enable Strict Checking of objc_msgSend Calls控制着OBJC_OLD_DISPATCH_PROTOTYPES的取值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息