温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

OC Rumtime中IMP函数调用的示例分析

发布时间:2021-10-21 14:07:09 来源:亿速云 阅读:218 作者:小新 栏目:开发技术

这篇文章主要为大家展示了“OC Rumtime中IMP函数调用的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“OC Rumtime中IMP函数调用的示例分析”这篇文章吧。

        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 - Preprocessing 的Enable Strict Checking of objc_msgSend Calls 选项设置为NO,否则result = imp(clazz, sel);会报错的!!”

于是按照上面说的进行了设置,运行成功。并且经过调试,发现确实是Enable Strict Checking of objc_msgSend Calls控制着OBJC_OLD_DISPATCH_PROTOTYPES的取值。

以上是“OC Rumtime中IMP函数调用的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI