一、简介
动态编程机制可以让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