云南 网站模版,天津网站建设 文率科技,嘉兴网站建设运营,网站开发摊销期一、遍历类的属性#xff0c;快速归档
在 iOS 中#xff0c;可以使用 Runtime 遍历类的属性来实现快速的归档#xff08;Archiving#xff09;操作。归档是将对象转换为数据流以便存储或传输的过程。下面是一个简单的示例#xff0c;展示如何使用 Runtime 遍历类的属性进…一、遍历类的属性快速归档
在 iOS 中可以使用 Runtime 遍历类的属性来实现快速的归档Archiving操作。归档是将对象转换为数据流以便存储或传输的过程。下面是一个简单的示例展示如何使用 Runtime 遍历类的属性进行归档操作
假设有一个名为 Person 的类我们想要对其属性进行归档操作
#import objc/runtime.hinterface Person : NSObject NSCoding
property (nonatomic, strong) NSString *name;
property (nonatomic, assign) NSInteger age;
endimplementation Person- (void)encodeWithCoder:(NSCoder *)coder {unsigned int count;objc_property_t *properties class_copyPropertyList([self class], count);for (int i 0; i count; i) {objc_property_t property properties[i];NSString *propertyName [NSString stringWithUTF8String:property_getName(property)];id propertyValue [self valueForKey:propertyName];[coder encodeObject:propertyValue forKey:propertyName];}free(properties);
}- (instancetype)initWithCoder:(NSCoder *)coder {self [super init];if (self) {unsigned int count;objc_property_t *properties class_copyPropertyList([self class], count);for (int i 0; i count; i) {objc_property_t property properties[i];NSString *propertyName [NSString stringWithUTF8String:property_getName(property)];id propertyValue [coder decodeObjectForKey:propertyName];[self setValue:propertyValue forKey:propertyName];}free(properties);}return self;
}end在上面的示例中encodeWithCoder: 方法遍历了 Person 类的所有属性并将属性的值使用 NSCoder 进行归桋操作。initWithCoder: 方法则对归档的数据进行解档恢复对象的状态。
通过使用 Runtime 遍历类的属性我们可以实现一个通用的归档和解档方法而无需手动编写大量的归档代码。这样可以提高代码的复用性和可维护性。
二、字典转模型
1、创建一个NSObject的分类
interface NSObject (Json)(instancetype)dictToModel:(NSDictionary *)dict;
end2、实现分类中字典转模型的方法
#import NSObjectJson.h
#import objc/runtime.himplementation NSObject (Json) (instancetype)dictToModel:(NSDictionary *)dict
{id obj [[self alloc] init];unsigned int count 0;Ivar *ivars class_copyIvarList([self class], count);for (int i0; icount; i) {Ivar ivar ivars[i];NSMutableString *name [NSMutableString stringWithUTF8String:ivar_getName(ivar)];[name deleteCharactersInRange:NSMakeRange(0, 1)]; [obj setValue:dict[name] forKey:name];}return obj;
}
end3、调用字典转模型的方法
- (void)viewDidLoad {[super viewDidLoad];NSMutableDictionary *dict [[NSMutableDictionary alloc] init];[dict setObject:张三 forKey:name];[dict setObject:20 forKey:age];[dict setObject:北京 forKey:address];Student *student [Student dictToModel:dict];NSLog(name:%\n,student.name);NSLog(age:%\n,student.age);NSLog(address:%\n,student.address);
}4、运行结果
2019-04-13 10:51:32.1365680800 AppLife[19195:4640916] name:张三
2019-04-13 10:51:32.1367070800 AppLife[19195:4640916] age:20
2019-04-13 10:51:32.1368030800 AppLife[19195:4640916] address:北京三 防止数组插入空值
1、创建一个NSMutableArray的分类
interface NSMutableArray (Extension)end2、实现分类中方法的交换
#import NSMutableArrayExtension.h
#import objc/runtime.himplementation NSMutableArray (Extension) (void)load {static dispatch_once_t onceToken;dispatch_once(onceToken, ^{Class cls NSClassFromString(__NSArrayM);Method method1 class_getInstanceMethod(cls, selector(insertObject:atIndex:));Method method2 class_getInstanceMethod(cls, selector(cs_insertObject:atIndex:));method_exchangeImplementations(method1, method2);});
}- (void)cs_insertObject:(id)anObject atIndex:(NSUInteger)index {if (anObject nil) {return;}[self cs_insertObject:anObject atIndex:index];
}end
3、调用
#import NSMutableArrayExtension.h
#import objc/runtime.himplementation NSMutableArray (Extension) (void)load {static dispatch_once_t onceToken;dispatch_once(onceToken, ^{Class cls NSClassFromString(__NSArrayM);Method method1 class_getInstanceMethod(cls, selector(insertObject:atIndex:));Method method2 class_getInstanceMethod(cls, selector(cs_insertObject:atIndex:));method_exchangeImplementations(method1, method2);});
}- (void)cs_insertObject:(id)anObject atIndex:(NSUInteger)index {if (anObject nil) {return;}[self cs_insertObject:anObject atIndex:index];
}end
4、运行结果
2019-04-13 11:24:19.5623630800 AppLife[20661:4661256] (Test
)运用Rutime中交换方法的思想还可以实现拦截所有按钮的点击时间和防止字典中插入空值等。
四、给分类添加属性
1、在分类里声明一个属性
#import Student.hinterface Student (Test)
property (nonatomic, copy) NSString *englishName;
end2、实现get和set方法
implementation Student (Test)- (void)setEnglishName:(NSString *)englishName
{// 第一个参数给哪个对象添加关联// 第二个参数关联的key通过这个key获取// 第三个参数关联的value// 第四个参数:关联的策略objc_setAssociatedObject(self, EnglishName, englishName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (NSString *)englishName
{return objc_getAssociatedObject(self, EnglishName);
}end
五、其他
(1) 实现第一个场景跟踪程序每个ViewController展示给用户的次数可以通过Method Swizzling替换ViewDidAppear初始方法。创建一个UIViewController的分类重写自定义的ViewDidAppear方法并在其load方法中实现ViewDidAppear方法的交换。
(2) 开发中常需要在不改变某个类的前提下为其添加一个新的属性尤其是为系统的类添加新的属性这个时候就可以利用Runtime的关联对象Associated Objects来为分类添加新的属性了。
(3) 实现字典的模型和自动转换优秀的JSON转模型第三方库JSONModel、YYModel等都利用runtime对属性进行获取赋值等操作要比KVC进行模型转换更加强大更有效率。阅读YYModel的源码可以看出YY大神对NSObject的内容进行了又一次封装添加了许多描述内容。其中YYClassInfo是对Class进行了再次封装而YYClassIvarInfo、YYClassMethodInfo、YYClPropertyInfo分别是对Class的Ivar、Method和property进行了封装和描述。在提取Class的相关信息时都运用了Runtime。