OC对象的序列化和反序列化

"应用程序包"结构:

    "应用程序包": 这里面存放的是应用程序的源文件,包括资源文件和可执行文件。

          NSString *path = [[NSBundle mainBundle] bundlePath];

    Documents:最常用的目录,iTunes同步该应用时会同步此文件夹中的内容,适合存储重要数据。

            NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject

      Library:

                    Caches:iTunes不会同步此文件夹,适合存储体积大,不需要备份的非重要数据

                                    NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

                    Preferences:iTunes同步该应用时会同步此文件夹中的内容,通常保存应用的设置信息。

    tmp: iTunes不会同步此文件夹,系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。

                    NSString *path = NSTemporaryDirectory();

这里我们说说归档

将数据结构或对象转换成二进制串的过程:序列化

将在序列化过程中所生成的二进制串转换成数据结构或者对象的过成:反序列化

归档在iOS中是一种形式的序列化,只要遵循了NSCoding协议的对象都可以通过它实现序列化。由于决大多数支持存储数据的Foundation和Cocoa Touch类都遵循了NSCoding协议,因此,对于大多数类来说,归档相对而言还是比较容易实现的。

1.遵循NSCoding协议:NSCoding协议声明了两个方法,这两个方法都是必须实现的。一个用来说明如何将对象编码到归档中,另一个说明如何进行解档来获取一个新对象。

2、保存文件的扩展名可以任意指定

3、继承时必须先调用父类的归档解档方法

4、都是覆盖存储

//告诉系统,归档哪些属性

- (void)encodeWithCoder:(NSCoder *)coder

{

    //利用runtime 来归档!!

    unsigned int count = 0;

    Ivar * ivars = class_copyIvarList([Person class], &count);


    for (int i = 0; i < count; i++) {

        //拿出每一个Ivar

        Ivar ivar = ivars[i];

        const char * name = ivar_getName(ivar);

        NSString * KEY = [NSString stringWithUTF8String:name];

        //归档

        [coder encodeObject:[self valueForKey:KEY] forKey:KEY];

    }


    //C语言里面!! 一旦遇到了copy creat new 需要释放

    free(ivars);


}

- (instancetype)initWithCoder:(NSCoder *)coder

{

    self = [super init];

    if (self) {

        unsigned int count = 0;

        Ivar * ivars = class_copyIvarList([Person class], &count);

        for (int i = 0; i < count; i++) {

            Ivar ivar = ivars[i];

            const char * name = ivar_getName(ivar);

            NSString * KEY = [NSString stringWithUTF8String:name];

            //解档

            id value = [coder decodeObjectForKey:KEY];

            //通过KVC 设置

            [self setValue:value forKey:KEY];

        }


        free(ivars);

    }

    return self;

}

NSUserDefault:一般来说,小规模数据,弱业务相关数据,都可以放到NSUserDefault里面,内容比较多的数据,强业务相关的数据就不太适合NSUserDefault了。另外我想吐槽的是,天猫这个App其实是没有一个经过设计的数据持久层的。然后天猫里面的持久化方案就很混乱,我就见到过有些业务线会把大部分业务数据都塞到NSUserDefault里面去,当时看代码的时候我特么就直接跪了。。。问起来为什么这么做?结果说因为写起来方便~你妹。。。

keychain:Keychain是苹果提供的带有可逆加密的存储机制,普遍用在各种存密码的需求上。另外,由于App卸载只要系统不重装,Keychain中的数据依旧能够得到保留,以及可被iCloud同步的特性,大家都会在这里存储用户唯一标识串。所以有需要加密、需要存iCloud的敏感小数据,一般都会放在Keychain。

文件存储:文件存储包括了Plist、archive、Stream等方式,一般结构化的数据或者需要方便查询的数据,都会以Plist的方式去持久化。Archive方式适合存储平时不太经常使用但很大量的数据,或者读取之后希望直接对象化的数据,因为Archive会将对象及其对象关系序列化,以至于读取数据的时候需要Decode很花时间,Decode的过程可以是解压,也可以是对象化,这个可以根据具体中的实现来决定。Stream就是一般的文件存储了,一般用来存存图片啊啥的,适用于比较经常使用,然而数据量又不算非常大的那种。

数据库存储:数据库存储的话,花样就比较多了。苹果自带了一个Core Data,当然业界也有无数替代方案可选,不过真正用在iOS领域的除了Core Data外,就是FMDB比较多了。数据库方案主要是为了便于增删改查,当数据有状态和类别的时候最好还是采用数据库方案比较好,而且尤其是当这些状态和类别都是强业务相关的时候,就更加要采用数据库方案了。因为你不可能通过文件系统遍历文件去甄别你需要获取的属于某个状态或类别的数据,这么做成本就太大了。当然,特别大量的数据也不适合直接存储数据库,比如图片或者文章这样的数据,一般来说,都是数据库存一个文件名,然后这个文件名指向的是某个图片或者文章的文件。如果真的要做全文索引这种需求,建议最好还是挂个API丢到服务端去做。

你可能感兴趣的:(OC对象的序列化和反序列化)