iOS中自动实现对象序列化的方法详解
程序员文章站
2023-12-19 23:45:22
前言
在ios 中实现对象序列化,需要遵行nscoding协议,然后对对象的每个属性进行归档和接档赋值,响应的操作比较繁琐。本文主要介绍 利用 runtime遍历属性 大...
前言
在ios 中实现对象序列化,需要遵行nscoding协议,然后对对象的每个属性进行归档和接档赋值,响应的操作比较繁琐。本文主要介绍 利用 runtime遍历属性 大大简化代码量,下面来看看详细的介绍吧。
具体实现代码如下:
1.先建立nsobject的分类, 定义可能用到的相关类型
static nsstring *inttype = @"i"; // int_32t(枚举int型) static nsstring *longtpye = @"l"; //long类型 static nsstring *longlongtype= @"q"; // longlong类型 static nsstring *booltype = @"b"; //bool类型 static nsstring *floattype = @"f"; // float static nsstring *doubletype = @"d"; // double static nsstring *booltype = @"c"; static nsstring *stringtype = @"nsstring"; // nsstring 类型 static nsstring *numbertype = @"nsnumber"; // nsnumber 类型 static nsstring *arraytype = @"arraytype";//array类型 static nsstring *imagetype = @"uiimage"; // uiimage 类型
然后在归档方法中便利自身的属性名称,并且取出自身属性对应的值,进行存储到本地。此时遍历类属性本身,用到了ivar指针(定义对象的实例变量,包括类型和名字),具体代码如下
//归档 - (void)encodewithcoder:(nscoder *)acoder { unsigned int count; // 属性个数 ivar *vararray = class_copyivarlist([self class], &count); for (int i = 0; i < count; i++) { ivar var = vararray[i]; const char *cname = ivar_getname(var); // 属性名c字符串 nsstring *proname = [[nsstring stringwithutf8string:cname] substringfromindex:1]; //oc字符串,并且去掉下划线 _ const char *ctype = ivar_gettypeencoding(var); // 获取变量类型,c字符串 id value = [self valueforkey:proname]; nsstring *protype = [nsstring stringwithutf8string:ctype]; // oc 字符串 if ([protype containsstring:@"nsstring"]) { protype = stringtype; } if ([protype containsstring:@"nsnumber"]) { protype = numbertype; } if ([protype containsstring:@"nsarray"]) { protype = arraytype; } if ([protype containsstring:@"uiimage"]) { protype = imagetype; } // (5). 根据类型进行编码 if ([protype isequaltostring:inttype] || [protype isequaltostring:booltype] || [protype isequaltostring:booltype]) { [acoder encodeint32:[value intvalue] forkey:proname]; } else if ([protype isequaltostring:longtpye]) { [acoder encodeint64:[value longvalue] forkey:proname]; } else if ([protype isequaltostring:floattype]) { [acoder encodefloat:[value floatvalue] forkey:proname]; } else if ([protype isequaltostring:longlongtype] || [protype isequaltostring:doubletype]) { [acoder encodedouble:[value doublevalue] forkey:proname]; } else if ([protype isequaltostring:stringtype]) { // string 类型 [acoder encodeobject:value forkey:proname]; } else if ([protype isequaltostring:numbertype]) { [acoder encodeobject:value forkey:proname]; } else if ([protype isequaltostring:arraytype]) { [acoder encodeobject:value forkey:proname]; } else if ([protype isequaltostring:imagetype]) { // image 类型 [acoder encodedataobject:uiimagepngrepresentation(value)]; } } free(vararray); }
其次进行解档, 原理和归档差不多, 直接上代码
- (instancetype)initwithcoder:(nscoder *)adecoder { self = [self init]; if (self) { unsigned int count; ivar *vararray = class_copyivarlist([self class], &count); for (int i = 0; i < count; i++) { ivar var = vararray[i]; const char *cname = ivar_getname(var); // 属性名c字符串 nsstring *proname = [[nsstring stringwithutf8string:cname] substringfromindex:1]; //oc字符串,并且去掉下划线 _ const char *ctype = ivar_gettypeencoding(var); // 获取变量类型,c字符串 nsstring *protype = [nsstring stringwithutf8string:ctype]; // oc 字符串 if ([protype containsstring:@"nsstring"]) { protype = stringtype; } if ([protype containsstring:@"nsnumber"]) { protype = numbertype; } if ([protype containsstring:@"nsarray"]) { protype = arraytype; } if ([protype containsstring:@"uiimage"]) { protype = imagetype; } if ([protype isequaltostring:inttype] || [protype isequaltostring:booltype] || [protype isequaltostring:booltype]) { int32_t number = [adecoder decodeint32forkey:proname]; [self setvalue:@(number) forkey:proname]; } else if ([protype isequaltostring:longtpye]) { int64_t number = [adecoder decodeint64forkey:proname]; [self setvalue:@(number) forkey:proname]; } else if ([protype isequaltostring:floattype]) { float number = [adecoder decodefloatforkey:proname]; [self setvalue:@(number) forkey:proname]; } else if ([protype isequaltostring:longlongtype] || [protype isequaltostring:doubletype]) { double number = [adecoder decodefloatforkey:proname]; [self setvalue:@(number) forkey:proname]; } else if ([protype isequaltostring:stringtype]) { // string 类型 nsstring *string = [adecoder decodeobjectforkey:proname]; [self setvalue:string forkey:proname]; } else if ([protype isequaltostring:numbertype]) { nsstring *number = [adecoder decodeobjectforkey:proname]; [self setvalue:number forkey:proname]; } else if ([protype isequaltostring:arraytype]) { nsarray *array = [adecoder decodeobjectforkey:proname]; [self setvalue:array forkey:proname]; } else if ([protype isequaltostring:imagetype]) { // image 类型 uiimage *image = [uiimage imagewithdata:[adecoder decodedataobject]]; [self setvalue:image forkey:proname]; } } } return self; }
最后也就是 存储方法 、 清除存储的本地缓存 和 获取本地存储数据的方法
//存储路径 - (nsstring *)filepathwithuniqueflagstring:(nsstring *)uniqueflag { nsstring *docpath = [nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes) lastobject]; nsstring *detailpath = [nsstring stringwithformat:@"%@_%@",uniqueflag,[nsstring stringwithutf8string:object_getclassname(self)]]; nsstring *path = [docpath stringbyappendingpathcomponent:detailpath]; return path; } //保存对象数据到本地 - (void)savedatatolocalwithuniqueflagkey:(nsstring *)uniqueflagkey { [nskeyedarchiver archiverootobject:self tofile:[self filepathwithuniqueflagstring:uniqueflagkey]]; } //清空本地存储的对象数据 - (id)getdatafromlocalwithuniqueflagkey:(nsstring *)uniqueflagkey { return [nskeyedunarchiver unarchiveobjectwithfile:[self filepathwithuniqueflagstring:uniqueflagkey]]; } //从本地获取对象数据 - (bool)removedatafromlocalwithuniqueflagkey:(nsstring *)uniqueflagkey { nserror *error = nil; [[nsfilemanager defaultmanager] removeitematpath:[self filepathwithuniqueflagstring:uniqueflagkey] error:&error]; if (!error) { return yes; } else { return no; } }
完整项目下载地址如下:https://github.com/maxzhang123/mxcoding.git 或者可以本地下载地址:http://xiazai.jb51.net/201705/yuanma/mxcoding(jb51.net).rar
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。