• IOS开发数据持久化篇文件存储(二)


    前言:个人觉得开发人员最大的悲哀莫过于懂得使用却不明白其中的原理.在代码之前我觉得还是有必要简单阐述下相关的一些知识点. 因为文章或深或浅总有适合的人群.若有朋友发现了其中不正确的观点还望多多指出,不胜感激.
    承接上篇博客我们来看看IOS开发中是如何将一个自定义的对象进行归档的
    本篇博客将介绍以下几个方面的内容
    1)普通的单个对象归档操作
    2)拥有继承关系的对象归档
    3)同时将多个对象进行归档
    1.普通的单个对象归档操作
    首先我们来看下最简单的单个对象归档操作
    1.自定义一个跟小明一样有名的类(Person)
    直接上代码 :
     Person.h
     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Person : NSObject<NSCoding>
     4 
     5 /**
     6  *  姓名
     7  */
     8 @property (nonatomic, strong) NSString *name ;
     9 
    10 /**
    11  *  地址
    12  */
    13 @property (nonatomic, strong) NSString *address ;
    14 
    15 /**
    16  *  年龄
    17  */
    18 @property (nonatomic, assign) int age;
    19 
    20 
    21 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age;//初始化方法
    22 
    23 @end

    Person.m

     1 #import "Person.h"
     2 
     3 @implementation Person
     4 
     5 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age{
     6     if (self = [super init]) {
     7         self.name = name;
     8         self.address = address;
     9         self.age = age;
    10     }
    11     return self;
    12 }
    13 
    14 //告知编译器,我们需要归档当前对象的哪些属性
    15 -(void)encodeWithCoder:(NSCoder *)aCoder{
    16     
    17     [aCoder encodeObject:self.name forKey:@"name"];
    18     [aCoder encodeObject:self.address forKey:@"address"];
    19     [aCoder encodeInt: self.age forKey:@"age"];
    20 }
    21 
    22 //告知编译器,解档时对应的属性
    23 -(instancetype)initWithCoder:(NSCoder *)aDecoder{
    24     
    25     self.name = [aDecoder decodeObjectForKey:@"name"];
    26     self.address = [aDecoder decodeObjectForKey:@"address"];
    27     self.age = [aDecoder decodeIntForKey:@"age"];
    28     return self;
    29 }
    30 
    31 //重写description,方便调试查看对象属性信息
    32 -(NSString *)description{
    33     return [NSString stringWithFormat:@"name : %@, address : %@,age : %d",self.name,self.address,self.age];
    34 }
    35 
    36 @end

    控制器代码1:归档

     1 -(void)personArchive{
     2     //创建及初始化对象
     3     Person *p = [[Person alloc] initWithName: @"jack" address:@"Mars" age:20];
     4     
     5     //定义归档路径
     6     NSString *fullPath = [self fullPathWithFileName:@"person.data"];
     7     
     8     //进行归档
     9     [NSKeyedArchiver archiveRootObject:p toFile:fullPath];
    10     
    11     NSLog(@"对象归档成功");
    12 }

    控制器代码2:解档

    1 -(void)personUnarchive{
    2     //指定路径
    3     NSString *fullPath = [self fullPathWithFileName:@"person.data"];
    4     //解档操作
    5     Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:fullPath];
    6     //打印结果
    7     NSLog(@"%@",p);
    8     
    9 }

    注: fullPathWithFileName: 方法为便捷获取路径方法,代码如下

    1 -(NSString *)fullPathWithFileName:(NSString *)fileName{
    2 
    3     NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    4     //拼接完整路径并返回
    5     return [documentDir stringByAppendingPathComponent:fileName];
    6 
    7 }

    依次调用我们的归档和解档方法

     [self personArchive];//归档
     [self personUnarchive];//解档

    结果如下:

    至此我们已经实现了简单的单个对象的归档和解档操作,下面我们来看下继承关系下的对象的归档解档操作

    2.拥有继承关系的对象归档和解档

    定义一个Student类继承自Person类,代码如下

    Student.h

     1 #import "Person.h"
     2 
     3 @interface Student : Person
     4 
     5 /**
     6  *  学校名称
     7  */
     8 @property (nonatomic, strong) NSString *schoolName;
     9 //快速初始化方法
    10 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age schoolName:(NSString *)schoolName;
    11 
    12 @end

    Student.m

     1 #import "Student.h"
     2 
     3 @implementation Student
     4 
     5 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age schoolName:(NSString *)schoolName{
     6     if (self = [super initWithName:name address:address age:age]) {
     7         self.schoolName =schoolName;
     8     }
     9     return self;
    10 }
    11 
    12 
    13 -(void)encodeWithCoder:(NSCoder *)aCoder{
    14     
    15     [super encodeWithCoder:aCoder];
    16     
    17     [aCoder encodeObject:self.schoolName forKey:@"schoolName"];
    18 }
    19 
    20 -(instancetype)initWithCoder:(NSCoder *)aDecoder
    21 {
    22     self = [super initWithCoder:aDecoder];
    23     self.schoolName = [aDecoder decodeObjectForKey:@"schoolName"];
    24     return self;
    25 }
    26 
    27 //重写description,方便调试查看属性信息
    28 -(NSString *)description{
    29     
    30     //先拿到父类拥有的属性描述
    31     NSString *str = [super description];
    32     //添加子类特有的描述,返回
    33     return [str stringByAppendingString:[NSString  stringWithFormat:@",schoolName : %@",self.schoolName]];
    34 }
    35 @end

    控制器方法1:归档

     1 -(void)studentArchive{
     2     //声明一个子类对象
     3     Student *stu = [[Student alloc] initWithName:@"小明" address:@"走廊" age:10 schoolName:@"剑桥大学"];
     4     //定义路径
     5     NSString *fullpath = [self fullPathWithFileName:@"stu.data"];
     6     //归档操作
     7     [NSKeyedArchiver archiveRootObject:stu toFile:fullpath];
     8     
     9     NSLog(@"归档成功");
    10 }

    控制器方法2:解档

    1 -(void)studentUnarchive{
    2     
    3     NSString *fullpath = [self fullPathWithFileName:@"stu.data"];//指定路径
    4     Student *stu = [NSKeyedUnarchiver unarchiveObjectWithFile:fullpath];//解档
    5     NSLog(@"%@",stu);//打印信息
    6 }

    依次调用上述两个方法,运行结果如下

    3.同时将多个对象归档

    演示代码如下:

    1.归档

     1 -(void)multipleArchive{
     2     //创建并初始化两个对象
     3     Student *s0 = [[Student alloc]initWithName:@"name0" address:@"address0" age:10 schoolName:@"schoolName0"];
     4     Student *s1 = [[Student alloc]initWithName:@"name1" address:@"address1" age:20 schoolName:@"schoolName1"];
     5    
     6     //创建一个NSMutableData对象
     7     NSMutableData *data = [NSMutableData data];
     8     NSKeyedArchiver *archive = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];//关联
     9     
    10     [archive encodeObject:s0 forKey:@"student0"];
    11     [archive encodeObject:s1 forKey:@"student1"];
    12     
    13     [archive finishEncoding];
    14     //指定路径
    15     NSString *fullpath = [self fullPathWithFileName:@"multiple.data"];
    16     //到这一步数据已缓存到data中,将其写入文件
    17     [data writeToFile:fullpath atomically:YES];
    18     
    19     NSLog(@"多对象归档成功");
    20 
    21 }

    02.解档:

     1 -(void)multipleUnArchive{
     2     
     3     NSString *fullpath = [self fullPathWithFileName:@"multiple.data"];//指定路径
     4     NSData *data = [NSData dataWithContentsOfFile:fullpath];//将数据解析成NSData对象
     5     NSKeyedUnarchiver *unArchive = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];//关联
     6     Student *stu0 = [unArchive decodeObjectForKey:@"student0"];
     7     Student *stu1 = [unArchive decodeObjectForKey:@"student1"];
     8     [unArchive finishDecoding];
     9     NSLog(@"%@",stu0);
    10     NSLog(@"%@",stu1);
    11 
    12 }

    运行结果如下图:

    4.分析与简单总结
    1.将一个对象归档的前提:
    遵守NSCoding协议
    实现两个方法:
    encodeWithCoder://指定需要归档的属性
    initWithCoder://指定需要解档的属性
    2.继承关系的对象归档注意:
    在实现上述两个方法的时候记得调用其父类的方法
    eg:
    [super encodeWithCoder:aCoder];
    self = [super initWithCoder:aDecoder];
    3.多对象归档依赖于:NSData对象
  • 相关阅读:
    VS远程调试项目,利用msvsmon
    web deploy发布网站各种问题
    IOS中UITabBar、UIDatePicker、Picker View控件练习(二)
    IOS中多视图应用视图切换
    IOS中多视图应用设置首界面
    Asp.net中Application Session Cookie ViewState Cache Hidden
    UI控件(scrollView、tableView)的基本使用
    UI错误集
    UI小项目之拳皇动画的实现(抽取加载图片和播放音乐的方法)
    UI控件(Label、ImageView、Button)的基本使用
  • 原文地址:https://www.cnblogs.com/cboyce/p/5128709.html
Copyright © 2020-2023  润新知