一、Runtime介绍
Runtime是Objective-C的运行时库,由C和汇编实现。通过Runtime封装的C结构体和函数在运行时创建、检查、修改类及对象及其方法,甚至可以替换或交换方法的实现。使用runtime解决问题的好处经常是比较高效,而且不用导入头文件
二、项目里面的使用
1. 接口返回的NSDictionary里面有NSNull对象的情况。Method Swizzling
// 新建NSDictionary的category
- (id)nullObjectForKey:(id)attr{
return [[self nullObjectForKey:attr] isEqual:[NSNull null]] ? nil : [self nullObjectForKey:attr];
}
+ (void)load{
Method method1 = class_getInstanceMethod(self, @selector(objectForKey:));
Method method2 = class_getInstanceMethod(self, @selector(nullObjectForKey:));
method_exchangeImplementations(method1, method2);
}
2. 修改整个项目里面的字体,详见方法如下,这样可以做到放心的使用系统字体,实际上显示的是自定义字体
/**@return因为交换了方法实现,手动调用此方法返回的是系统字体。不建议主动去调用*/
+ (instancetype)wjFontOfSize:(CGFloat)fontSize{
return [UIFont fontWithName:@"STHeitiSC-Light" size:fontSize];
}
+ (void)load{
Method method1 = class_getClassMethod(self, @selector(systemFontOfSize:));
Method method2 = class_getClassMethod(self, @selector(wjFontOfSize:));
method_exchangeImplementations(method1, method2);
}
3. 动态属性关联,有时想在category关联一个属性(运行时无法动态添加属性)
//Cat+Extend.h
@interface Cat (extend)
@property(nonatomic, copy) NSString *name;
@end
//Cat+Extend.m
@implementation Cat (extend)
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, "name");
}
@end
4. 字典转模型时,遍历类的属性,给模型赋值。MJExtension里面是这样实现转模型的
5. 实现NSCoding的自动归档和自动解档
//解档
- (instancetype)initWithCoder:(NSCoder*)aDecoder{
if(self= [super init]) {
Classc = self.class;
// 截取类和父类的成员变量
while(c && c != [NSObject class]) {
unsigned int count =0;
Ivar* ivars = class_copyIvarList(c, &count);
for(int i =0; i < count; i++) {
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivars[i])];
id value = [aDecoder decodeObjectForKey:key];
if(value) {
[self setValue:value forKey:key];
}
}
// 获得c的父类
c = [c superclass];
free(ivars);
}
}
return self;
}
//归档
- (void)encodeWithCoder:(NSCoder*)aCoder{
Class c =self.class;
// 截取类和父类的成员变量
while(c && c != [NSObject class]) {
unsigned int count =0;
Ivar *ivars = class_copyIvarList(c, &count);
for(int i =0; i < count; i++) {
Ivar ivar = ivars[i];
NSString*key = [NSString stringWithUTF8String:ivar_getName(ivar)];
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
c = [c superclass];
// 释放内存
free(ivars);
}
}
三、引用文章:
网友评论