欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > > 编程问答 >内容正文

编程问答

ios序列化与反序列化,本地化 -凯发k8官方网

发布时间:2025/1/21 编程问答 6 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 ios序列化与反序列化,本地化 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

2019独角兽企业重金招聘python工程师标准>>>

你是用什么方法来持久保存数据的?这是在几乎每一次关于ios技术的交流或讨论都会被提到的问题,而且大家对这个问题的热情持续高涨。本文主要从概念上把“数据存储”这个问题进行剖析,并且结合各自特点和适用场景给大家提供一个选择的思路,并不详细介绍某一种方式的技术细节。

谈到数据储存,首先要明确区分两个概念,数据结构和储存方式。所谓数据结构就是数据存在的形式。除了基本的nsdictionary、nsarray和nsset这些对象,还有更复杂的如:关系模型、对象图和属性列表多种结构。而存储方式则简单的分为两种:内存与闪存。内存存储是临时的,运行时有效的,但效率高,而闪存则是一种持久化存储,但产生i/o消耗,效率相对低。把内存数据转移到闪存中进行持久化的操作称成为归档。

二者结合起来才是完整的数据存储方案,我们最常谈起的那些:sqlite、coredata、nsuserdefaults等都是数据存储方案。当然在这些框架提供的方案之外,我们自己也可以按照个性化需求订制方案。这些存储方案侧重不同,支持的形式和方式也各不相同,在不同的使用场景下表现也是各有优劣。但万变不离其宗,无论什么方案都可以用下图来解释。

图1,存储方案示意图

以下将对四种存储方式进行详细的介绍:

  • nsuserdefaults,用于存储配置信息

  • sqlite,用于存储查询需求较多的数据

  • coredata,用于规划应用中的对象

  • 使用基本对象类型定制的个性化缓存方案

nsuserdefaults存储配置信息

nsuserdefaults被设计用来存储设备和应用的配置信息,它通过一个工厂方法返回默认的、也是最常用到的实例对象。这个对象中储存了系统中用户的配置信息,开发者可以通过这个实例对象对这些已有的信息进行修改,也可以按照自己的需求创建新的配置项。

图2,笔者手机中[nsuserdefaults standarduserdefaults]内容

nsuserdefaults把配置信息以字典的形式组织起来,支持字典的项包括:字符串或者是数组,除此之外还支持数字等基本格式。一句话概括就是:基础类型的小数据的字典。操作方法几乎与nsdictionary的操作方法无异,另外还可以通过指定返回类型的方法获取到指定类型的返回值。

图3,nsuserdefaults提供的指定返回类型的方法列表

nsuserdefaults的所有数据都放在内存里,因此操作速度很快,并还提供一个归档方法: (void)synchronize。开发者自定义的配置项(如图2中的最后一项 key:alkdjfkladsjfmm)会以plist格式的文件归档在相应应用目录的/library/preferences/[app_bundle_identifier].plist文件。再次初始化获得实例对象后,框架会把用户自定义的这个配置和系统配置合并得到完整数据。

sqlite存储查询需求较多的数据

ios的sdk里预置了sqlite的库,开发者可以自建sqlite数据库。sqlite每次写入数据都会产生io消耗,把数据归档到相应的文件。

sqlite擅长处理的数据类型其实与nsuserdefaults差不多,也是基础类型的小数据,只是从组织形式上不同。开发者可以以关系型数据库的方式组织数据,使用sql dml来管理数据。 一般来说应用中的格式化的文本类数据可以存放在数据库中,尤其是类似聊天记录、timeline等这些具有条件查询和排序需求的数据。

每一个数据库的句柄都会在内存中都会被分配一段缓存,用于提高查询效率。另一个方面,由于查询缓存,当产生大量句柄或数据量较大时,会出现缓存过大,造成内存浪费。

sqlite的使用起来要比nsuserdefaults复杂的多,因此建议开发者使用sqlite要搭配一个操作控件使用,可以简化操作。笔者开发的sqlight是一款对sqlite操作的封装,把相对复杂的sqlite命令封装成对象和方法,可以供大家参考。大家可以在github上获取这个工程的代码进一步了解。

coredata规划应用中对象

官方给出的定义是,一个支持持久化的,对象图和生命周期的自动化管理方案。严格意义上说coredata是一个管理方案,他的持久化可以通过sqlite、xml或二进制文件储存。如官方定义所说,coredata的作用远远不止储存数据这么简单,它可以把整个应用中的对象建模并进行自动化的管理。

图4,官方文档中解释coredata给出的对象图示例

正如上图所示,mydocument是一个对象实例,有两个collection:employee和department,存放各自的对象列表。mydocument、employee和department三个对象以及他们之间的关系都通过coredata建模,并可以通过save方法进行持久化。

从归档文件还原模型时coredata并不是一次性把整个模型中的所有数据都载入内存,而是根据运行时状态,把被调用到的对象实例载入内存。框架会自动控制这个过程,从而达到控制内存消耗,避免浪费。

无论从设计原理还是使用方法上看,coredata都比较复杂。因此,如果仅仅是考虑缓存数据这个需求,coredata绝对不是一个优选方案。coredata的使用场景在于:整个应用使用coredata规划,把应用内的数据通过coredata建模,完全基于coredata架构应用。

苹果官方给出的一个示例代码,结构相对简单,可以帮助大家入门coredata。

obj-c中有一类对象:nsarray,nsdictionary,nsstring,nsnumber,nsdate,nsdata以及它们的可变版本(指nsmutablearray,nsmutabledictionary...这一类) ,都可以方便的将自身的数据以某种格式(比如xml格式)序列化后保存成本地文件。



示例代码:nsarraytest.h

#import  #define file_name @"/tmp/data.txt"@interface nsarraytest : nsobject {   }-(void) test;@end #import "nsarraytest.h"@implementation  nsarraytest-(void) test {nsarray *arr = [nsarray arraywithobjects:@"one",@"two",@"three",nil];      //注:最后一个要以nil结尾[arr writetofile:file_name atomically:yes];         //(序列化为xml格式后)保存文件nsarray *arr2 = [nsarray arraywithcontentsoffile:file_name];         //read filenslog(@"%@",arr2);}@end


运行结果:nsarraytest.m

2011-03-03 14:20:01.501 plist[1246:a0f] (
    one,
    two,
    three
)

如果查看/tmp/data.txt,能看到下面的内容:

onetwothree

即nsarray默认是以xml格式来序列化对象的.

如果你用来存放数据的类是自己定义的,并不是上面这些预置的对象,那么就要借助正式协议nscoding来实现序列化和反序列化。


比如,我们有一个自己的类sample.h

#import @interface sample : nsobject {nsstring* name;int magicnumber;float shoesize;nsmutablearray *subthingies; }@property(copy) nsstring* name; @property int magicnumber; @property float shoesize; @property (retain) nsmutablearray *subthingies;-(id) initwithname:(nsstring *)n magicnumber:(int)m shoesize:(float) ss;@end

这里我们定义几个不同类型的属性,有字符串,有整数,有浮点数,还有一个可变长的数组对象

sample.m

#import "sample.h"@implementation sample@synthesize name; @synthesize magicnumber; @synthesize shoesize; @synthesize subthingies;-(id) initwithname:(nsstring *)n magicnumber:(int)m shoesize:(float)ss {if (self=[super init]){self.name = n;self.magicnumber = m;self.shoesize = ss;self.subthingies = [nsmutablearray array];}return (self); }-(void) dealloc {[name release];[subthingies release];[super dealloc]; }//将对象编码(即:序列化) -(void) encodewithcoder:(nscoder *)acoder {[acoder encodeobject:name forkey:@"name"];[acoder encodeint:magicnumber forkey:@"magicnumber"];[acoder encodefloat:shoesize forkey:@"shoesize"];[acoder encodeobject:subthingies forkey:@"subthingies"]; }//将对象解码(反序列化) -(id) initwithcoder:(nscoder *)adecoder {if (self=[super init]){self.name = [adecoder decodeobjectforkey:@"name"];self.magicnumber = [adecoder decodeintforkey:@"magicnumber"];self.shoesize = [adecoder decodefloatforkey:@"shoesize"];self.subthingies = [adecoder decodeobjectforkey:@"subthingies"];}return (self);}-(nsstring*) description {nsstring *description = [nsstring stringwithformat:@"%@:%d/%.1f %@",name,magicnumber,shoesize,subthingies];return (description); }@end

注意其中的:encodewithcoderinitwithcoder,这是nscoding协议中定义的二个方法,用来实现对象的编码与解码。其实现也不复杂,利用的是key-value的经典哈希结构。当然一般在编码中,对于key的名字字符串,建议用define以常量方式事先定义好,以避免开发人员字符串键入错误。

测试一下:

#import  #import "sample.h"int main (int argc, const char * argv[]) {nsautoreleasepool * pool = [[nsautoreleasepool alloc] init]; sample *s1 = [[sample alloc] initwithname:@"thing1" magicnumber:42 shoesize:10.5]; [s1.subthingies addobject:@"1"];[s1.subthingies addobject:@"2"];nslog(@"%@",s1); nsdata *data1 = [nskeyedarchiver archiveddatawithrootobject:s1];//将s1序列化后,保存到nsdata中[s1 release];[data1 writetofile:@"/tmp/data.txt" atomically:yes];//持久化保存成物理文件nsdata *data2 = [nsdata datawithcontentsoffile:@"/tmp/data.txt"];//读取文件 sample *s2 = [nskeyedunarchiver unarchiveobjectwithdata:data2];//反序列化 nslog(@"%@",s2);[pool drain];return 0; }

运行结果:

2011-03-03 14:36:48.540 plist[1322:a0f] thing1:42/10.5 (
    1,
    2
)
2011-03-03 14:36:48.548 plist[1322:a0f] thing1:42/10.5 (
    1,
    2
)

查看/tmp/data.txt,能看到以下内容:

由于经过了编码,里面的内容没有象前面的nsarray那样可读性强。


有关序列化和反序列化内容转自如下地址:

http://www.cnblogs.com/yjmyzz/archive/2011/03/03/1969859.html


转载于:https://my.oschina.net/sayonala/blog/305624

总结

以上是凯发k8官方网为你收集整理的ios序列化与反序列化,本地化的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

网站地图