当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS中自动实现对象序列化的方法详解

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

2019年07月24日  | 移动技术网移动技术  | 我要评论
前言 在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  或者可以本地下载地址:

总结

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

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网