RunTime

参考文档1
参考文档2
参考文档3

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容