iOS 反射函数: performSelector, NSInvocation, objc_msgSend
当我们有方法名和参数列表,想要动态地给对象发送消息,可用通过反射函数机制来实现,有两种常用的做法:
一、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的更多相关文章
- iOS 消息处理之performSelector
//// RootViewController.h// DSCategories//// Created by dasheng on 15/12/17.// Copyright © 2015年 ...
- iOS 基础函数解析 - Foundation Functions Reference
iOS 基础函数解析 - Foundation Functions Reference 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名- ...
- iOS 反射 学习 和 运用
iOS 反射 学习 和 运用 反射: 通过 类名来获得生成的相应的类的实例 的这种机制 叫 反射 常用的反射方式 把 NSDictionary 转成 自定义 model 自定义 model 转 ...
- ios反射
http://www.cr173.com/html/18677_1.html 1.反射获取类属性名和属性类型 unsigned ; objc_property_t *properties = clas ...
- iOS多线程中performSelector: 和dispatch_time的不同
iOS中timer相关的延时调用,常见的有NSObject中的performSelector:withObject:afterDelay:这个方法在调用的时候会设置当前runloop中timer,还有 ...
- 我也要学iOS逆向工程--函数
大家好,这篇我开始学习函数了.先学 C 函数,然后再 OC 的吧.OC 应该复杂点的吧. 然后看看汇编情况哦! 学习函数呢,肯定要弄清楚几个事情. 1.跳转地址. 2.返回地址 3.参数 4.函数获取 ...
- iOS反射机制
iOS属性反射:说白了,就是将两个对象的所有属性,用动态的方式取出来,并根据属性名,自动绑值.(注意:对象的类,如果是派生类,就得靠其他方式来实现了,因为得到不该基类的属性.) 本人常用的反射方式,有 ...
- iOS多线程中performSelector
下面两段代码都在主线程中运行,我们在看别人代码时会发现有时会直接调用,有时会利用performSelector调用,今天看到有人在问这个问题,我便做一下总结, [delegate imageDownl ...
- U3D开发中关于脚本方面的限制-有关IOS反射和JIT的支持问题
U3D文档中说明了,反射在IOS是支持的,除了system.reflection.emit空间内的,其它都支持.JIT是不支持的. 本质上来说即是:只要不在运行时动态生成代码的行为都支持,reflec ...
随机推荐
- python基础 3.0 file 读取文件
一.python 文件访问 1.在python中要访问文件,首先要打开文件,也就是open r: 只读 w: 只写 ,文件已存在则清空,不存在则创建 a:追加 ,写到文件末尾.如果文件存在,则在 ...
- tomcat mamcached session共享方法
下载后输入命令安装命令: c:\memcached\memcached.exe -d install 然后再输入如下命令把其作为win service常驻启动: c:\memcached\memcac ...
- poj2186-Popular Cows(强连通分支)
有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1 ...
- myeclipse 上安装 Maven
myeclipse 上安装 Maven3 环境准备: JDK 1.6 Maven 3.0.4 myeclipse 8.6.1 安装 Maven 之前要求先确定你的 JDK 已经安装配置完成.Mav ...
- 关于jetty的那些奇葩问题
Jetty的解压目录并不像Tomcat那样直接是在webapps下,如果你什么都不做修改的话,Ubuntu14.04下Jetty的默认解压目录是/var/cache/jetty/data/下: 比如我 ...
- Ubuntu14.04下sogou输入法的输入框只显示英文不显示中文的问题
解决方法:首先强制更新,把依赖文件全部安装 sudo apt-get install -f 如果仍然不管用,删除sogou的配置文件,在~/.config目录下,一般情况下是SogouPY.Sogou ...
- 整理一下postgresql的扩展功能postgis和pgrouting的使用
postgis windows的下的安装使用postgresql的bin目录下的stackbuiler Ubuntu14.04下的安装: apt-get install postgresql-9.3- ...
- IIS下FTP服务器的PASV端口范围修改方法
应该有不少使用IIS自带的FTP服务器,IIS的FTP里的PASV模式下默认端口范围1024 - 65535,连接时会从中随机选择到响应.这样的超大范围就给服务器安全带来的隐患. 虽然可以通过一些方法 ...
- 批量 多个JPG生产PDF .net C#
using iTextSharp.text; using iTextSharp.text.pdf; using System; using System.Collections.Generic; us ...
- 关于wav文件fft处理后x,y轴坐标数据的问题
1.关于横坐标的频率的最大值是采样频率,那么每个点对应的频率值就很好算了:f(n) = [Fs/(N/2)]*n (Fs是采样频率,常见的是44.1KHz(44100),N是采样点数,k表是第k个点 ...