欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS中自动实现对象序列化的方法详解

程序员文章站 2024-02-13 09:22:34
前言 在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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。