RunTime在项目中使用较少,但需要时运用确能事半功倍。项目中对其进行了封装,这里只简单码一下简单的应用。
两道试题起
- 第一题
@implementation Son : Father
-(id)init{
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
打印结果都是Son.
self 是类的隐藏参数,指向当前调用方法的这个类的实例。
super 本质是一个编译器标示符,和 self 是指向的同一个消息接受者。
不同的是,super告诉编译者从父类类调用方法,如果父类没有,只能去NSObject中。
NSObject 这个类调用的class 方法时,返回的都是son.
- 第二道题
@interface Sark : NSObject
@end
@implementation Sark
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]];
BOOL res4 = [(id)[Sark class] isMemberOfClass:[Sark class]];
NSLog(@"%d %d %d %d", res1, res2, res3, res4);
}
return 0;
}
打印结果:1,0,0,0;
类目中可以扩展方法,但由于类目并不是一个类,不能扩展属性。如果定义属性则不生成相应的实例变量(实例变量是由类定义的变量),没有实现相应的setter 和 getter 方法。即使实现了setter和getter方法也无法保存数据。但可以通过runTime属性关联,变通添加属性。
属性关联
@interface UIViewController (Category)
@property (nonatomic,strong) NSString *name;
@end
*********数据实质的存储位置*********
static char nameKey ;
//static const char *key = "name";
-(void)setName:(NSString *)name{
objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)name{
return objc_getAssociatedObject(self, &nameKey);
}
需要给某个类添加方法时,可重写父类方法,也可以runtime交换方法。但重写会覆盖父类方法,且不能调用super.
方法交换
implementation UIImage (Image)
// 加载分类到内存的时候调用
// 一般方法交换会写在这个方法中
+(void)load{
// 获取imageWithName方法地址
Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));
// 获取imageWithName方法地址
Method imageName = class_getClassMethod(self, @selector(imageNamed:));
// 交换方法地址,相当于交换实现方式
method_exchangeImplementations(imageWithName, imageName);
}
// 不能在分类中重写系统方法imageNamed,
// 因为会把系统的功能给覆盖掉,而且分类中不能调用super.
// 既能加载图片又能打印
+ (instancetype)imageWithName:(NSString *)name{
// 这里调用imageWithName,相当于调用imageNamed
// 因为这里已经将方法完成了交换
UIImage *image = [self imageWithName:name];
if (image == nil) {
NSLog(@"加载空的图片");
}
return image;
}
@end