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 ...
随机推荐
- 黑马SSM项目练习中的Oracle操作
- 最长双回文串(模板+dp)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ , f ...
- LeetCode初级算法(树篇)
目录 二叉树的最大深度 验证二叉搜索树 对称二叉树 二叉树的层次遍历 将有序数组转换为二叉搜索树 二叉树的最大深度 二叉树,所以可以考虑用递归来做.由于根节点已经算过了,所以需要加上1:每次返回都是以 ...
- Angular学习笔记【如何正确使用第三方组件】
例如:ng-bootstrap的使用: 1.首先肯定是先要安装,参考官网给出的指令安装即可.(npm install --save @ng-bootstrap/ng-bootstrap) 2.在App ...
- .db文件打开方式
有时在工作中,数据库格式db后缀的格式,直接是打不开的,所以我这里使用了数据库管理工具,步骤如下 1. 在电脑安装 Navicat Premium,安装后在桌面生成图标,点击图标打开程序. 2.打开程 ...
- python_魔法方法(五):描述符和定制序列
描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...
- HDU 4143 A Simple Problem 分解因式
求一个最小的正整数x,使得(y + x) (y - x) = n成立 考虑一下n的分解因式. 可能会想到枚举n的约数,那么a * b = n成立,取最小的x即可 但是要枚举到n / 2,这样会超时. ...
- VMware安装CentOS7的详细过程
原文:https://www.jianshu.com/p/ce08cdbc4ddb?utm_source=tuicool&utm_medium=referral 本篇文章主要介绍了VMware ...
- 【Unity3D/C#】利用IEnumerable<>和yield产生斐波那契数列
using UnityEngine; using System.Collections; using System.Collections.Generic; public class YieldTes ...
- 【Unity3D】用继承EditorUpdater类来实现Editor模式下的后台处理
EditorWindow类的OnGUI函数只会在窗口焦点处于Editor窗口上的时候才会运行.如果希望焦点不在Editor窗口上的时候,它也能实时更新,可以实现以下方法: OnDestroy OnDe ...