iOS开发:Object-C的反射机制

一、简介

动态编程机制可以让Object-C语言更加灵活,Object-C提供了3种编程方式与运行环境交互。

1.直接通过Object-C的源代码。这是最常见的方式

2.通过NSObject类中定义的方法进行动态编程。

3.直接调用运行时函数进行动态编程。

二、获得Class与检查继承关系

1.获得Class,先创建一个Animal对象

    //通过类名获取类
    Class clazz = NSClassFromString(@"Animal");
    NSLog(@"获取到的类为:%@",clazz);
    //通过类获取类
    Class clazz1 = Animal.class;
    NSLog(@"获取到的类为:%@",clazz1);
    //通过对象获取类
    Animal * animal = [[clazz alloc] init];
    Class clazz2 = animal.class;
    NSLog(@"获取到的类为:%@",clazz2);

输出的结果为:

2016-06-15 13:30:26.217 继承关系-test[10930:404401] 获取到的类为:Animal

2016-06-15 13:30:26.218 继承关系-test[10930:404401] 获取到的类为:Animal

2016-06-15 13:30:26.218 继承关系-test[10930:404401] 获取到的类为:Animal


2.检查继承关系,创建两个继承自Animal的对象分别为Person和Dog;

    Person * person = [[Person alloc] init];
    Dog* dog = [[Dog alloc] init];
    //判断是否是该类或其子类的实例。
    bool bl = [person isKindOfClass:[Animal class]];
    //判断是否是该类的实例
    bool bl1 = [person isMemberOfClass:[Animal class]];
    bool bl2 = [person isKindOfClass:[Dog class]];
    NSLog(@"是否为该类或其子类:%d",bl);//1
    NSLog(@"是否为为该类:%d",bl1);//0
    NSLog(@"是否为该类或其子类:%d",bl2);//0

三、动态调用方法

1.判断是否遵从了某项协议,指定animalDelegate协议

#import <Foundation/Foundation.h>
@protocol animalDelegate <NSObject>

-(void)testFun;
@end

@interface Animal : NSObject

@end

若Dog类没有遵从协议

#import <Foundation/Foundation.h>
#import "Animal.h"
@interface Dog : Animal

@end
调用方法

    Dog* dog = [[Dog alloc] init];
    //是否遵从了协议
    bool bl = [dog conformsToProtocol:@protocol(animalDelegate)];
    NSLog(@"%d",bl);//0
当遵从了协议后

#import <Foundation/Foundation.h>
#import "Animal.h"
@interface Dog : Animal<animalDelegate>

@end
调用方法

    Dog* dog = [[Dog alloc] init];
    //是否遵从了协议
    bool bl = [dog conformsToProtocol:@protocol(animalDelegate)];
    NSLog(@"%d",bl);//1

2.判断某个对象是否可以调用某个方法

    //可以调用返回yes,不可以返回no
    bl = [dog respondsToSelector:@selector(testFun)];
    NSLog(@"%d",bl);
三、动态调用

给Dog类添加私有方法

-(NSString *)moveWithSpeed:(NSNumber *)speed{
    NSLog(@"移动");
    NSInteger num = [speed integerValue];
    return [NSString stringWithFormat:@"移动速度:%ld",num];
}

-(NSString *)runWithSpeed:(NSNumber*)speed{
    
    NSLog(@"快跑");
    NSInteger num = [speed integerValue];
    return [NSString stringWithFormat:@"快跑速度:%ld",num];
}

利用动态方法调用这两个方法

Dog* dog = [[Dog alloc] init];
//动态调用方法
    //方法一:performSelector
    //参数可以传1个或2个。若要传入多个参数可以用集合的方式实现。
    //返回值id
    NSString * speed = [dog performSelector:@selector(moveWithSpeed:) withObject:[NSNumber numberWithInteger:5]];
    NSLog(@"speed:%@",speed);
    NSString * speed1 = [dog performSelector:@selector(moveWithSpeed:) withObject:@(5) withObject:nil];
    NSLog(@"speed1:%@",speed1);
    
    //方法二:objc_msgSend();
    //需要在project-Build Setting- Enable Strict Checking of objc_msgSend Calls 选项设置为NO;
    //可以传入任意个参数。第一个为方法的调用者,  第二个为@selector(方法名),后边为方法需要传入的参数可以有多个。
    //返回值为id,
    NSString * speed2 = objc_msgSend(dog, @selector(runWithSpeed:),@(5),nil);
    NSLog(@"speed2:%@",speed2);
    
    //方法三:methodForSelector
    //1.定义IMP指针 指针变量为runSpeed
    NSString* (*runSpeed)(id,SEL,NSNumber*);
    //2-1.methodForSelector:方法返回的是IMP。
    //2-2.通过(NSString* (*)(id,SEL,NSNumber*))对返回的IMP进行类型强转。
    runSpeed = (NSString* (*)(id,SEL,NSNumber*))[dog methodForSelector:@selector(runWithSpeed:)];
    //通过runSpeed指针调用方法,并拿到返回值。
    NSString * speed3 = runSpeed(dog,@selector(runWithSpeed:),@(100));
    NSLog(@"speed3:%@",speed3);

输出结果为:

2016-06-15 14:00:31.209 继承关系-test[11662:423726] 移动

2016-06-15 14:00:31.209 继承关系-test[11662:423726] speed:移动速度:5

2016-06-15 14:00:31.209 继承关系-test[11662:423726] 移动

2016-06-15 14:00:31.209 继承关系-test[11662:423726] speed1:移动速度:5

2016-06-15 14:00:31.209 继承关系-test[11662:423726] 快跑

2016-06-15 14:00:31.210 继承关系-test[11662:423726] speed2:快跑速度:5

2016-06-15 14:00:31.210 继承关系-test[11662:423726] 快跑

2016-06-15 14:00:31.210 继承关系-test[11662:423726] speed3:快跑速度:100













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值