IOS利用objc/runtime和KVC——快速归档解档
开发过程中有时需要存储一些轻量级的数据,对于IOS提供的几种数据存储方式在这时最合适当属对象归档:NSCoding
但是将对象数据进行归档解档时候需要实现两个方法: encodeWithCoder和initWithEncoder。encodeWithCoder就是编码,initWithCoder就是解码。
encodeWithCoder方法传入的是一个NSCoder对象,实现的时候我们就可以调用encodeObject、encodeFloat、 encodeInt等各种方法并通过指定键值进行编码,而
在需要的时候调用decodeDoubleForKey,decodeFloatForKey,decodeObjectForKey进行解码。
1.实现encodeWithCoder和initWithEncoder
#import "MyModel.h" @implementation MyModel #define kCUSTIDKey @"CUSTIDKey" #define kCUSTSTATUSKey @"CUSTSTATUSKey" #define kPICTUREIDKey @"PICTUREIDKey" #define kUNITNUMKey @"UNITNUMKey" #define kCITYIDKey @"CITYIDKey" #define kCUSTNAMEKey @"CUSTNAMEKey" #define kCOMMUNITYNAMEKey @"COMMUNITYNAMEKey" #define kRESERVE1Key @"RESERVE1Key" #define kCITYKey @"CITYKey" #define kCOMMUNITYIDKey @"COMMUNITYIDKey" #define kCITYNAMEKey @"CITYNAMEKey" #define kBUILDINGNUMKey @"BUILDINGNUMKey" #define kNICKNAMEKey @"NICKNAMEKey" #define kHOUSENUMKey @"HOUSENUMKey" #define kPHONEKey @"PHONEKey" //归档 - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.CUSTID forKey:kCUSTIDKey]; [aCoder encodeObject:self.CUSTSTATUS forKey:kCUSTSTATUSKey]; [aCoder encodeObject:self.PICTUREID forKey:kPICTUREIDKey]; [aCoder encodeObject:self.UNITNUM forKey:kUNITNUMKey]; [aCoder encodeObject:self.PHONE forKey:kPHONEKey]; [aCoder encodeObject:self.CITYID forKey:kCITYIDKey]; [aCoder encodeObject:self.CUSTNAME forKey:kCUSTNAMEKey]; [aCoder encodeObject:self.COMMUNITYNAME forKey:kCOMMUNITYNAMEKey]; [aCoder encodeObject:self.RESERVE1 forKey:kRESERVE1Key]; [aCoder encodeObject:self.CITY forKey:kCITYKey]; [aCoder encodeObject:self.COMMUNITYID forKey:kCOMMUNITYIDKey]; [aCoder encodeObject:self.CITYNAME forKey:kCITYNAMEKey]; [aCoder encodeObject:self.BUILDINGNUM forKey:kBUILDINGNUMKey]; [aCoder encodeObject:self.NICKNAME forKey:kNICKNAMEKey]; [aCoder encodeObject:self.HOUSENUM forKey:kHOUSENUMKey]; } // 解档 - (id)initWithCoder:(NSCoder *)decoder { if (self = [super init]) { self.CUSTID = [decoder decodeObjectForKey:kCUSTIDKey]; self.CUSTSTATUS = [decoder decodeObjectForKey:kCUSTSTATUSKey]; self.PICTUREID = [decoder decodeObjectForKey:kPICTUREIDKey]; self.PHONE = [decoder decodeObjectForKey:kPHONEKey]; self.UNITNUM = [decoder decodeObjectForKey:kUNITNUMKey]; self.CITYID = [decoder decodeObjectForKey:kCITYIDKey]; self.CUSTNAME = [decoder decodeObjectForKey:kCUSTNAMEKey]; self.COMMUNITYNAME = [decoder decodeObjectForKey:kCOMMUNITYNAMEKey]; self.RESERVE1 = [decoder decodeObjectForKey:kRESERVE1Key]; self.CITY = [decoder decodeObjectForKey:kCITYKey]; self.COMMUNITYID = [decoder decodeObjectForKey:kCOMMUNITYIDKey]; self.CITYNAME = [decoder decodeObjectForKey:kCITYNAMEKey]; self.BUILDINGNUM = [decoder decodeObjectForKey:kBUILDINGNUMKey]; self.NICKNAME = [decoder decodeObjectForKey:kNICKNAMEKey]; self.HOUSENUM = [decoder decodeObjectForKey:kHOUSENUMKey]; } return self; } @end
写完之后发现整个人都不好了,如果对象属性更多,这些重复性的代码也意味着要被Command+C Command+V着N次,累觉无爱。
然后尝试用其他方式进行,既然Objective-C运行时库提供了非常便利的方法获取其对象运行时所属类及其所有成员变量,并通过KVC进行值的存取,那么或者可以这样objc/runtime+KVC
导入#import <objc/runtime.h>头文件
//获取类中所有属性 unsigned int count; Ivar *varA = class_copyIvarList([MyModel class], &count); for (unsigned int i=0; i<count; i++) { Ivar v = varA[i]; const char *name = ivar_getName(v); NSLog(@"%s==",name); }
打印LOG:
好用,继续,利用KVC进行取值,根据属性名称获取对应的值
//KVC取值 id value = [self valueForKey:strName]; [encoder encodeObject:value forKey:strName];
最终改后的程序:
#import "MyModel.h" #import <objc/runtime.h> @implementation MyModel //解档 - (id)initWithCoder:(NSCoder *)decoder { if (self = [super init]) { unsigned int count = 0; //获取类中所有成员变量名 Ivar *ivar = class_copyIvarList([MyModel class], &count); for (int i = 0; i<count; i++) { Ivar iva = ivar[i]; const char *name = ivar_getName(iva); NSString *strName = [NSString stringWithUTF8String:name]; //进行解档取值 id value = [decoder decodeObjectForKey:strName]; //利用KVC对属性赋值 [self setValue:value forKey:strName]; } free(ivar); } return self; } //归档 - (void)encodeWithCoder:(NSCoder *)encoder { unsigned int count; Ivar *ivar = class_copyIvarList([MyModel class], &count); for (int i=0; i<count; i++) { Ivar iv = ivar[i]; const char *name = ivar_getName(iv); NSString *strName = [NSString stringWithUTF8String:name]; //利用KVC取值 id value = [self valueForKey:strName]; [encoder encodeObject:value forKey:strName]; } free(ivar); } @end
妥妥的了,远离重复,做开心玩耍的程序媛!