前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ios开发 Runtime 详解part2(动态方法解析)

ios开发 Runtime 详解part2(动态方法解析)

作者头像
Leacode
发布2018-08-22 14:13:56
6910
发布2018-08-22 14:13:56
举报
文章被收录于专栏:代码散人

ios开发 Runtime 详解part1中我已经解释了Introspection,接下来介绍Runtime的其它特性。

Runtime能做什么?

1、Introspection, 获得对象中的信息,如Class, Selector(SEL), Method:

ios开发 Runtime 详解part1

2、Dynamic Method Resolution (动态方法解析)

在苹果的文档里给出了一个动态添加c方法的例子: 例子, 我在这里做一些扩展:

首先我在RuntimeObject.h类中添加三个方法:

代码语言:javascript
复制
- (void)addInstanceMethod: (NSString *)str; // 添加实例方法

+ (void)addClassMethod: (NSString *)str; // 添加类方法

- (void)addCMethod; // 添加c方法

在RuntimeObject.m中我们有三个方法:

代码语言:javascript
复制
/**

动态绑定的实例方法

@param str 传递的参数

*/

- (void)instanceMethod: (NSString *)str {

NSLog(@"execute instance Method, pass value: %@", str);

}

/**

动态绑定的类方法

@param str 传递的参数

*/

+ (void)classMethod: (NSString *)str {

NSLog(@"execute class Method, pass value: %@", str);

}

/**

动态绑定的c方法, 至少包含self和_cmd两个参数

@param self c方法必须传递

@param _cmd c方法必须传递

*/

void dynamicMethodIMP(id self, SEL _cmd) {

printf("execute C Method");

}

现在我们需要通过调用.h文件里的方法来执行.m里对应绑定的方法:

代码语言:javascript
复制
[ro addInstanceMethod: @"instance method"];

[RuntimeObject addClassMethod: @"class method"];

[ro addCMethod];

此时调用一定是会出错的,因为我们还没有进行动态绑定,要绑定RuntimeObject.m中的三个方法,我们需要借助实现resolveInstanceMethod和resolveClassMethod这两个方法来动态添加我们需要绑定的方法:

代码语言:javascript
复制
+ (BOOL)resolveInstanceMethod:(SEL)aSEL{

if (aSEL == @selector(addInstanceMethod:)) {

class_addMethod([self class], aSEL, class_getMethodImplementation([self class], @selector(instanceMethod:)), "v@:");

NSLog(@"%@", @"dynamicMethodIMP added");

return YES;

} else if (aSEL == @selector(addCMethod)) {

class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");

return YES;

}

return [super resolveClassMethod:aSEL];

}

+ (BOOL)resolveClassMethod:(SEL)aSEL {

if (aSEL == @selector(addClassMethod:)) {

class_addMethod(object_getClass(self), aSEL, class_getMethodImplementation(object_getClass(self), @selector(classMethod:)), "v@:");

return YES;

}

return [super resolveClassMethod:aSEL];

}

要注意,添加实例方法和类方法均是调用了runtime里class_addMeghod方法,这个方法结构如下:

代码语言:javascript
复制
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);

cls: 是要将方法添加到的目标类

name: 是一个selector,指定添加的方法的名字

imp: 实现的新方法,必须包含self和_cmd两个参数,由于oc的方法中默认有这两个参数,在代码中不必特别添加,但是c的方法需要加上这两个参数。

types: 描述参数的类型,由于方法都含有self和_cmd两个参数,第二个字符一定是@"", 而第一个字符表示返回值的类型, 我们这里因为返回值是void就用v表示,第三个字符表示一个方法的selector,我们放':'来表示,所以types传入"v@:",此处类型的编码可以在这里查看: 类型编码

要注意的是当self是类对象的时候,调用self class返回的是self,要获得class,需要通过object_getClass(self)来获得,否则会出错。

动态方法解析可以让我们像对属性修饰@dynamic一样,不让系统提供实现的方法,自定义方法的实现,也可以用来绑定c的方法来进行实现,一旦绑定,我们也可以用performSelector来直接调用.m里绑定的方法:

代码语言:javascript
复制
[ro addInstanceMethod: @"instance method"];  // 动态绑定了instanceMethod:方法

if ([ro respondsToSelector: @selector(instanceMethod:)]) {

[ro performSelector:@selector(instanceMethod:) withObject:@"call instance method"];

//  输出: execute instance Method, pass value: call instance method

}

此文介绍了Dynamic Method Resolution (动态方法解析)的用法,希望能对你有所帮助。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.10.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档