以前我們APP都是使用mj的mode賦值比驻,但是感覺(jué)有點(diǎn)繁瑣该溯,每次都要導(dǎo)入第三方,太過(guò)麻煩别惦,于是到網(wǎng)上查找了一下可以使用的方法狈茉,總結(jié)一下,第一次寫(xiě)掸掸,寫(xiě)的不好請(qǐng)大家原諒啊氯庆。
首先想到的是讀取類(lèi)的屬性名稱(chēng),拿到名稱(chēng)之后扰付,與從后臺(tái)拿到的數(shù)據(jù)進(jìn)行對(duì)比取值堤撵,于是馬上上網(wǎng)查找讀取類(lèi)的屬性名稱(chēng)的方法。代碼如下:
//這個(gè)是一點(diǎn)要導(dǎo)入的不然會(huì)出錯(cuò)
//這個(gè)是一點(diǎn)要導(dǎo)入的不然會(huì)出錯(cuò)
//這個(gè)是一點(diǎn)要導(dǎo)入的不然會(huì)出錯(cuò)
//重要的事情要說(shuō)三遍
#import <objc/runtime.h>
- (NSArray*)attributeArray
{
NSMutableArray*props = [NSMutableArrayarray];
unsignedintoutCount, i;
//讀取所以的屬性信息
objc_property_t*properties =class_copyPropertyList([selfclass], &outCount);
for(i =0; i
{
objc_property_tproperty = properties[i];
constchar* name =property_getName(property);
NSString*propertyName = [NSStringstringWithUTF8String:name];
[propsaddObject:propertyName];
}
free(properties);
returnprops;
}
到這里就可以讀取到所以的所有的屬性名稱(chēng)了羽莺,但是經(jīng)過(guò)測(cè)試發(fā)現(xiàn)粒督,這個(gè)只能讀取到當(dāng)前類(lèi)的屬性名,不可以讀取父類(lèi)的屬性名稱(chēng)禽翼,也就是讀取的屬性名不全,如:
這樣的話(huà)雖然也可以進(jìn)行賦值族跛,但是太過(guò)于死板闰挡。
后來(lái)在想,要是反過(guò)來(lái)是不是可以進(jìn)行賦值呢礁哄,讀取字典中所有的key长酗,根據(jù)key進(jìn)行查找屬性名進(jìn)行賦值,于是進(jìn)行了測(cè)試桐绒,發(fā)現(xiàn)這樣的話(huà)可以對(duì)父類(lèi)屬性進(jìn)行賦值夺脾,但是如果字典中存在沒(méi)有聲明的屬性名,在賦值的時(shí)候就會(huì)蹦蹦蹦茉继。
再想一下咧叭,如果可以判斷一下這個(gè)屬性是不是存在那不就可以避免對(duì)沒(méi)有聲明的屬性賦值報(bào)錯(cuò)的問(wèn)題了么,但是怎么查找屬性是否存在呢烁竭?又陷入了一個(gè)難點(diǎn)菲茬。
大家都知道屬性都有兩個(gè)方法的,就是get跟set方法派撕,get方法就是屬性的屬性名婉弹,那能不能根據(jù)一個(gè)字符串轉(zhuǎn)成一個(gè)方法呢,又是一番查找终吼,功夫不負(fù)有心人镀赌,找到了:
//通過(guò)字符串來(lái)創(chuàng)建該字符串的get方法,并返回
- (SEL)nameTransferMethod:(NSString*)propertyName{
//1.返回get方法: oc中的get方法就是屬性的本身
returnNSSelectorFromString(propertyName);
}
然后再進(jìn)行判斷一下這個(gè)get方法是否存在际跪,如果不存在的話(huà)就說(shuō)明沒(méi)有這個(gè)屬性商佛,這樣一來(lái)就解決了對(duì)沒(méi)有聲明的屬性賦值的問(wèn)題了喉钢。
- (void)assignmentInformationQuickly:(NSDictionary*)dictionary
{
NSArray* attributes = dictionary.allKeys;
for(NSString* keyinattributes) {
if([selfrespondsToSelector:[selfnameTransferMethod:key]]) {
[selfsetValue:dictionary[key]forKey:key];
}
?} ?
}
但是這樣的話(huà)會(huì)存在一些值沒(méi)辦法保存下來(lái),可能這些值很重要但是沒(méi)有保存進(jìn)而丟失(如:后臺(tái)返回過(guò)來(lái)的時(shí)候給的key為id威彰,但是不能創(chuàng)建一個(gè)屬性出牧,屬性名為id)。這里又想去一個(gè)可以借鑒的方法歇盼,對(duì)這樣的key進(jìn)行了轉(zhuǎn)換舔痕,中間使用一個(gè)字典進(jìn)行存儲(chǔ)這些對(duì)應(yīng)關(guān)系,想到這就馬上去實(shí)現(xiàn)了豹缀。對(duì)上面的方法做了一下簡(jiǎn)單的修改:
- (void)assignmentInformationQuickly:(NSDictionary*)dictionary
{
NSArray* attributes = dictionary.allKeys;
for(NSString* keyinattributes) {
if([selfrespondsToSelector:[selfnameTransferMethod:key]]) {
[selfsetValue:dictionary[key]forKey:key];
}else{
NSString* newKey =self.propertyMapDic[key];
if([selfrespondsToSelector:[selfnameTransferMethod:newKey]]) {
[selfsetValue:dictionary[key]forKey:newKey];
}
}
}
}
大家看到這個(gè)方法會(huì)不會(huì)迷惑呢伯复?
[selfsetValue:dictionary[key]forKey:key];?
這個(gè)就是根據(jù)屬性名給屬性賦值的一個(gè)方法,可以各種運(yùn)行邢笙。原理類(lèi)似于給字典添加鍵值對(duì)(鍵已存在的那種)啸如,大家可以實(shí)驗(yàn)一下;
最后附上完整代碼:
#import? <Foundation/Foundation.h>
@interfaceNSObject (ZZLModel)
///字典內(nèi)的key都與類(lèi)的屬性名對(duì)應(yīng)可以直接使用
- (instancetype)initWithDictionary:(NSDictionary*)dictionary;
///賦值信息
- (void)assignmentInformationQuickly:(NSDictionary*)dictionary;
#pragma返回屬性和字典key的映射關(guān)系
/**
*如果出現(xiàn)數(shù)據(jù)源的key值與類(lèi)的屬性不對(duì)應(yīng)的情況需要重寫(xiě)get方法如下:
- (NSDictionary *)propertyMapDic
{
if (![super propertyMapDic]) {
self.propertyMapDic = @{@"string7" : @"string6"};
}
return [super propertyMapDic];
}
*屬性與字典key的映射key為數(shù)據(jù)源字典中的key值為類(lèi)里面的屬性名字
*/
@property(nonatomic,strong)NSDictionary* propertyMapDic;
@end
.m
#import"ZZLModel.h"
//這個(gè)是一點(diǎn)要導(dǎo)入的不然會(huì)出錯(cuò)
//這個(gè)是一點(diǎn)要導(dǎo)入的不然會(huì)出錯(cuò)
//這個(gè)是一點(diǎn)要導(dǎo)入的不然會(huì)出錯(cuò)
//重要的事情要說(shuō)三遍
#import<objc/runtime.h>
staticcharconst*constproperty_Map_Dic ="property_Map_Dic";
@implementationNSObject (ZZLModel)
- (instancetype)initWithDictionary:(NSDictionary*)dictionary
{
if(self= [selfinit]) {
[selfassignmentInformationQuickly:dictionary];
//[self printMothList];
}
returnself;
}
- (void)assignmentInformationQuickly:(NSDictionary*)dictionary
{
NSArray* attributes = dictionary.allKeys;
for(NSString* keyinattributes) {
if([selfrespondsToSelector:[selfnameTransferMethod:key]]) {
[selfsetValue:dictionary[key]forKey:key];
}else{
NSLog(@"%@",self.propertyMapDic);
NSString* newKey =self.propertyMapDic[key];
if([selfrespondsToSelector:[selfnameTransferMethod:newKey]]) {
[selfsetValue:dictionary[key]forKey:newKey];
}
}
}
}
- (NSDictionary*)propertyMapDic {
returnobjc_getAssociatedObject(self,property_Map_Dic);
}
- (void)setPropertyMapDic:(id)propertyMapDic {
objc_setAssociatedObject(self,property_Map_Dic, propertyMapDic,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#pragma mark --通過(guò)字符串來(lái)創(chuàng)建該字符串的Setter方法氮惯,并返回
- (SEL)nameTransferMethod:(NSString*)propertyName{
//1.返回get方法: oc中的get方法就是屬性的本身
returnNSSelectorFromString(propertyName);
}
- (NSArray*)attributeArray
{
NSMutableArray*props = [NSMutableArrayarray];
unsignedintoutCount, i;
//讀取所以的屬性信息
objc_property_t*properties =class_copyPropertyList([selfclass], &outCount);
for(i =0; i
{
objc_property_tproperty = properties[i];
constchar* name =property_getName(property);
NSString*propertyName = [NSStringstringWithUTF8String:name];
[propsaddObject:propertyName];
}
free(properties);
returnprops;
}
/*獲取對(duì)象的所有方法*/
-(void)printMothList
{
unsignedintmothCout_f =0;
Method* mothList_f =class_copyMethodList([selfclass],&mothCout_f);
for(inti=0;i
{
Methodtemp_f = mothList_f[i];
IMPimp_f =method_getImplementation(temp_f);
SELname_f =method_getName(temp_f);
constchar* name_s =sel_getName(method_getName(temp_f));
intarguments =method_getNumberOfArguments(temp_f);
constchar* encoding =method_getTypeEncoding(temp_f);
NSLog(@"方法名:%@,參數(shù)個(gè)數(shù):%d,編碼方式:%@",[NSStringstringWithUTF8String:name_s],
arguments,[NSStringstringWithUTF8String:encoding]);
}
free(mothList_f);
}
這里面是寫(xiě)的一個(gè)類(lèi)目叮雳,一個(gè)NSObject的類(lèi)目。
如果出現(xiàn)上面說(shuō)的那種一些重要屬性沒(méi)辦法存儲(chǔ)妇汗,可以在mode中重新propertyMapDic的get方法帘不,如下:
- (NSDictionary*)propertyMapDic
{
if(![super propertyMapDic]) {
self.propertyMapDic=@{@"string7":@"string6"};
}
return[super propertyMapDic];
}
下面是我的實(shí)驗(yàn):
成功啦 ? ?哈哈哈
就到這里了 ?謝謝大家杨箭;