当我们有方法名和参数列表,想要动态地给对象发送消息,可用通过反射函数机制来实现,有两种常用的做法:

一、performSelector

 - (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

常用的方法有这三个,其中aSelector可以通过 NSSelectorFromString 方法拿到

SEL aSelector = NSSelectorFromString(selString);

但是 performSelector 的缺点是最多只支持传递两个参数

http://my.oschina.net/ososchina/blog/644117

这篇文章给出的方法二说是可以支持多参数,但是我尝试了下未成功

二、NSInvocation

不多说,直接上栗子

// 测试反射函数
- (void)printWithString:(NSString *)string withNum:(NSNumber *)number withArray:(NSArray *)array {
NSLog(@"%@, %@, %@", string, number, array[]);
} - (void)test {
NSString *str = @"哈哈哈";
NSNumber *num = @;
NSArray *arr = @[@"ABC", @"DEF"];
// [self printWithString:str withNum:num withArray:arr];
SEL sel = NSSelectorFromString(@"printWithString:withNum:withArray:");
NSArray *objs = [NSArray arrayWithObjects:str, num, arr, nil];
[self performSelector:sel withObjects:objs];
} - (id)performSelector:(SEL)selector withObjects:(NSArray *)objects
{
// 方法签名(方法的描述)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
if (signature == nil) { //可以抛出异常也可以不操作。
} // NSInvocation : 利用一个NSInvocation对象包装一次方法调用(方法调用者、方法名、方法参数、方法返回值)
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector; // 设置参数
NSInteger paramsCount = signature.numberOfArguments - ; // 除self、_cmd以外的参数个数
paramsCount = MIN(paramsCount, objects.count);
for (NSInteger i = ; i < paramsCount; i++) {
id object = objects[i];
if ([object isKindOfClass:[NSNull class]]) continue;
[invocation setArgument:&object atIndex:i + ];
} // 调用方法
[invocation invoke]; // 获取返回值
id returnValue = nil;
if (signature.methodReturnLength) { // 有返回值类型,才去获得返回值
[invocation getReturnValue:&returnValue];
} return returnValue;
}

三、objc_msgSend

objc_msgSend的写法要复杂一点,具体可以参看这篇文章,讲的很清楚

http://www.jianshu.com/p/efeb33712445

但是有个缺点是,需要指定好传递参数的类型,是不是可以直接都用id呢?

经测试id可用

// objc_msgSend
SEL sel = NSSelectorFromString(@"printWithString:withNum:withArray:");
((void (*) (id, SEL, NSString *, NSNumber *, NSArray *)) objc_msgSend) (self, sel, str, num, arr);

iOS 反射函数: performSelector, NSInvocation, objc_msgSend的更多相关文章

  1. iOS 消息处理之performSelector

    ////  RootViewController.h//  DSCategories////  Created by dasheng on 15/12/17.//  Copyright © 2015年 ...

  2. iOS 基础函数解析 - Foundation Functions Reference

    iOS 基础函数解析 - Foundation Functions Reference 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名- ...

  3. iOS 反射 学习 和 运用

    iOS  反射 学习 和 运用 反射:  通过 类名来获得生成的相应的类的实例 的这种机制  叫 反射 常用的反射方式 把 NSDictionary  转成 自定义 model 自定义 model 转 ...

  4. ios反射

    http://www.cr173.com/html/18677_1.html 1.反射获取类属性名和属性类型 unsigned ; objc_property_t *properties = clas ...

  5. iOS多线程中performSelector: 和dispatch_time的不同

    iOS中timer相关的延时调用,常见的有NSObject中的performSelector:withObject:afterDelay:这个方法在调用的时候会设置当前runloop中timer,还有 ...

  6. 我也要学iOS逆向工程--函数

    大家好,这篇我开始学习函数了.先学 C 函数,然后再 OC 的吧.OC 应该复杂点的吧. 然后看看汇编情况哦! 学习函数呢,肯定要弄清楚几个事情. 1.跳转地址. 2.返回地址 3.参数 4.函数获取 ...

  7. iOS反射机制

    iOS属性反射:说白了,就是将两个对象的所有属性,用动态的方式取出来,并根据属性名,自动绑值.(注意:对象的类,如果是派生类,就得靠其他方式来实现了,因为得到不该基类的属性.) 本人常用的反射方式,有 ...

  8. iOS多线程中performSelector

    下面两段代码都在主线程中运行,我们在看别人代码时会发现有时会直接调用,有时会利用performSelector调用,今天看到有人在问这个问题,我便做一下总结, [delegate imageDownl ...

  9. U3D开发中关于脚本方面的限制-有关IOS反射和JIT的支持问题

    U3D文档中说明了,反射在IOS是支持的,除了system.reflection.emit空间内的,其它都支持.JIT是不支持的. 本质上来说即是:只要不在运行时动态生成代码的行为都支持,reflec ...

随机推荐

  1. 原生JS实现日历

    这周写自己的项目发现又用到日历了,加之自己毕业之后的第一个工作中遇到的任务也是需要写个日历(组员写了,我就不用写了) 今天就来好好折腾一下日历是怎么写的. 首先,我们看看 windows 的日历.发现 ...

  2. JS键盘事件之键控Div

    自上次做的鼠标拖动Div之后,看到fgm.cc的例子,发现用键盘操控Div貌似也是十分有趣,这些DOM操作随着jquery的没落,虽然渐渐少用了,不过有些DOM操作还是必不可少的.现在是虽然数据为王( ...

  3. Luogu P2833 等式 我是傻子x2

    又因为调一道水题而浪费时间...不过细节太多了$qwq$,暴露出自己代码能力的不足$QAQ$ 设$d=gcd(a,b)$,这题不是显然先解出来特解,即解出 $\frac{a}{d}x_0+\frac{ ...

  4. Docker从入门到实战(三)

    Docker从入门到实战(三) 一:安装Docker 1. linux系统脚本安装 Docker基于linux容器技术,面向服务器端,Docker只能安装运行在64位计算机上(社区有对32位的支持), ...

  5. Python 添加模块

    一.方法1: 单文件模块直接把文件拷贝到 $python_dir/Lib 二.方法2: 多文件模块,带setup.py 下载模块包,进行解压,进入模块文件夹,执行:python setup.py in ...

  6. IDEA/Eclipse安装 Alibaba Java Coding Guidelines 插件

    为了让开发者更加方便.并且达到快速规范代码格式的目的并实行起来,阿里巴巴基于<阿里巴巴Java开发规约>手册内容,研发了一套自动化的IDE检测插件(IDEA.Eclipse).它就是Ali ...

  7. UICollectionView笔记1

    WWDC 2012 Session笔记——205 Introducing Collection Views 这是博主的WWDC2012笔记系列中的一篇,完整的笔记列表可以参看这里.如果您是首次来到本站 ...

  8. 扒前端网页js代码

    红框是前端代码:输出script中 的内容 可以把红色区域的前端代码 转为java代码 来扒别的网站前端代码 转换成java代码之后,在控制台输入以下代码,点击回车则可以去打印出当前网页上的js fo ...

  9. codevs 1664 清凉冷水

    1664 清凉冷水 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold         题目描述 Description 闷热的夏天,威斯康辛州的奶制品地区提供冷水供奶牛 ...

  10. Vue2.0搭建脚手架(vue-cli)

    一.安装node.js 进入官网下载node.js 二.安装 cnpm 1.说明:npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理 ...