IOS开发反射和动态调用总结

和java一样,Object-C也提供了反射的机制。

每一个类都有一个Class,获取Class有以下三种方法。

// insert code here...
        //通过字符串获取class
        Class   clazz = NSClassFromString(@"NSString");
        NSLog(@"clazz的类型是%@",clazz);
        //直接用calzz 来创建对象
        id str  = [[clazz alloc] init];
        //通过对象来获取class
        NSLog(@"%@",[str class]);
        //通过类来获取class
        NSLog(@"%d",clazz==NSString.class);
        NSLog(@"Hello, World!");
    /**
        2015-04-28 17:03:18.907 反射[1322:303] clazz的类型是NSString
        2015-04-28 17:03:19.279 反射[1322:303] __NSCFConstantString
        2015-04-28 17:03:19.280 反射[1322:303] 1
        2015-04-28 17:03:19.281 反射[1322:303] Hello, World!
        Program ended with exit code: 0
       打印出来的结果是这样,_NSString只是类簇的前端而已
     **/

对与第一种和第二种方式,都是根据类获取Class对象,比较之下,第一种代码安全性更高,程序再编译阶段就可以检测所需要访问的Class是否存在。性能更高,因为无需调用方法。

动态调用的方法如下。直接上代码

#import <Foundation/Foundation.h>
@interface JQCar : NSObject

@end

#import "JQCar.h"
#import <objc/message.h>
@implementation JQCar
- (void)move:(NSNumber*)count{
    int num  = [count intValue];
    for (int i=0; i<num; i++) {
        NSLog(@"%@",[NSString stringWithFormat:@"汽车正在路上行走%d",i]);
    }
}
- (double)addSpeed:(double)factor{
  //动态调用move方法
 //使用performSelector动态调用move方法
    [self performSelector:@selector(move:) withObject:[NSNumber numberWithInt:2]];
    [self performSelector:NSSelectorFromString(@"move:") withObject:[NSNumber numberWithInt:2]];
    //使用objc_msgSend()函数动态调用
    objc_msgSend(self,@selector(move:),[NSNumber numberWithInt:2]);
    objc_msgSend(self, NSSelectorFromString(@"move:"),[NSNumber numberWithInt:3]);
    NSLog(@"正在加速%g",factor);
    return 100*factor;
}
@end
使用objc_msgSend可能报错
//objc_msgSend()报错Too many arguments to function call ,expected 0,have3

解决方法
//Build Setting--> Apple LLVM 6.0 - Preprocessing--> Enable Strict Checking of objc_msgSend Calls  改为 NO

#import <Foundation/Foundation.h>
#import <objc/message.h>
#import "JQCar.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        //获取JQCar类
        Class clazz = NSClassFromString(@"JQCar");
        //动态创建car
        id car  = [[clazz alloc] init];
        //使用performSelector方法来动态调用
        [car performSelector:@selector(addSpeed:) withObject:[NSNumber numberWithLong:2]];
        //使用Objec_send来动态调用
        objc_send(car,@selector(addSpeed:),3.4);
        //定义函数指针变量
        double (*addSpeed)(id ,SEL,double);
        //获取car对象的addSpeed方法,再把addSpeed方法赋值给addSpeed指针变量
        addSpeed = (double (*)(id,SEL,double))[car methodForSelector:NSSelectorFromString(@"addSpeed:")];
        //调用addSpeed
        double speed = addSpeed(car, @selector(addSpeed:), 3.4);
        NSLog(@"加速后的速度是%g",speed);
        
        NSLog(@"Hello, World!");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值