- 運(yùn)用runtime創(chuàng)建基類,也可以快速方便的實(shí)現(xiàn)model 與字典的相互轉(zhuǎn)化
- 下面的方法只是實(shí)現(xiàn)簡單的字典轉(zhuǎn)model,要實(shí)現(xiàn)復(fù)合model及包含數(shù)組的模型轉(zhuǎn)換還需要做一其它處理。
- 各種json 轉(zhuǎn) model大都都使用運(yùn)行時動態(tài)獲取屬性名的方法,來過行字典轉(zhuǎn)模型,但都使用了KVC :setValue:forKey,只是多了一些判空和嵌套的邏輯處理。
#import "NSObject+JsonExtension.h" //對基類添加擴(kuò)展
#import <objc/runtime.h> //一定要導(dǎo)入runtime頭文件
@implementation NSObject (JsonExtension)
+ (instancetype)objectWithDic:(NSDictionary*)dic{
NSObject *obj = [[self alloc]init];
[obj setDic:dic];
return obj;
}
- (void)setDic:(NSDictionary*)dic{
Class c = [self class];
while (c && c != [NSObject class]) {
unsigned int count = 0;
// Method *methodList = class_copyMethodList(c, &count);
//列舉屬性及實(shí)例變量
//Ivar *ivars = class_copyIvarList(c, &count);
//只列舉用@property修飾的屬性
objc_property_t *propertyList = class_copyPropertyList(c, &count);
for (int i = 0; i< count; i++) {
objc_property_t property = propertyList[i];
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
id value = dic[propertyName];
//值nil,說明字典的key沒有相應(yīng)model屬性
if (value == nil; continue;
[self setValue:value forKeyPath:propertyName];
}
//釋放數(shù)組
free(propertyList);
//從本類到父類
c = [c superclass];
}
}
@end
PS: 關(guān)于runtime,除了字典轉(zhuǎn)model外,常用的就是方法交換
一般不建議在分類中重寫當(dāng)前類的方法,因?yàn)槎鄠€類目都重寫一個方法后,系統(tǒng)無法確定重寫后的方法優(yōu)先級,同時重寫也覆蓋系統(tǒng)方法,且在類目中無法使用super.
#import <objc/runtime.h>
#import "UIImage+Extentsion.h"
@implementation UIImage (Extentsion)
+ (instancetype)imageWithName:(NSString*)name{
//方法已經(jīng)交換,所以這邊實(shí)際上調(diào)用的是系統(tǒng)方法
//即imageNamed:調(diào)用的是新的方法,而imageWithName:則是調(diào)用系統(tǒng)方法,而不是自身。
UIImage *image = [self imageWithName:name];
if (image == nil) {
NSLog(@"加載出錯");
}
NSLog(@"這是替換后的方法");
return image;
}
//分類加載到內(nèi)存時調(diào)用,且只調(diào)用一次
+ (void)load{
//class_getInstanceMethod(self, @selector(...)); //獲取實(shí)例方法
Method method1 = class_getClassMethod(self, @selector(imageWithName:));
Method method2 = class_getClassMethod(self, @selector(imageNamed:));
method_exchangeImplementations(method1, method2);
}
@end