2018-05-30 文件加载与保存

作者: 肠粉白粥_Hoben | 来源:发表于2018-05-30 17:13 被阅读2次

    一.属性列表

    在Cocoa中,有一类名为属性列表的对象,常简写为plist。这些列表包含Cocoa知道如何操作的一组对象,即Cocoa知道如何将他们保存到文件中并进行加载。包括NSArray、NSDictionary、NSString、NSNumber、NSDate、NSData,以及他们的变体。

    1.NSDate

    使用[NSDate date]获得当前的日期和时间。

    NSDate *date = [NSDate date];
    NSLog(@"%@", date);
    

    当然,可以获取任何时间,只要你知道那时候距离现在有多久。对于将来的时间用的时间间隔,对于过去的时间用的时间间隔。

    NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow: -(24 * 60 * 60)];
    NSLog(@"%@", yesterday);
    NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow: (24 * 60 * 60)];
    NSLog(@"%@", tomorrow);
    

    2.NSData

    NSData包装了大量字节,我们可以获得数据的长度和指向字节起始位置的一个指针。如果将数据块传递给一个函数或方法,可以通过传递一个自动释放的NSData来实现,无需担心内存清除问题。

    //char* 转 NSData
    const char * string = "Hi, I am Hoben Wong.";
    NSData *data = [NSData dataWithBytes: string length:strlen(string) + 1];
    //NSString 转 data
    NSString *string_NS = @"Hi, I am Hoben Wong.";
    NSData *data_NS = [string_NS dataUsingEncoding: NSUTF8StringEncoding];
    //NSData 转 char*
    NSLog(@"%s's length is %d", [data bytes], (int)[data length]);
    //NSData 转 NSString
    NSString *result = [[NSString alloc] initWithData: data_NS encoding:NSUTF8StringEncoding];
    NSLog(@"%@'s length is %d", result, (int)[result length]);
    

    二.编码、解码与归档

    1.为什么要用编码?

    • Size过大
    • 包含隐私数据
    • URL本身而言,歧义...
      对于最后一种比较常见,例如服务器通过截取& = 来区分你的key 和value。一旦你的参数中包含了&=则就会分割错误引起歧义从而需要编码。

    2.编码与解码

    采用NSCoding协议,可以使用自己的对象实现编解码功能。

    //NSCoding.h
    #import <Foundation/Foundation.h>
    
    @protocol NSCoding
    
    -(void) encodeWithCoder: (NSCoder *) aCoder;
    -(void) initWithCoder: (NSCoder *) aDecoder;
    
    @end
    

    通过采用该协议,可以实现两种功能:对象需要保存自身、对象需要加载自身。
    首先,在Thingie.h中实现NSCoder协议,并声明对象内容:

    //Thingie.h
    #import <Foundation/Foundation.h>
    
    @interface Thingie : NSObject <NSCoding>
    {
        NSString *name;
        int magicNumber;
        float shoeSize;
        NSMutableArray *subThingies;
    }
    
    @property (copy) NSString *name;
    @property int magicNumber;
    @property float shoeSize;
    @property NSMutableArray *subThingies;
    
    -(id) initWithName: (NSString *) n
            magicNumer: (int) mn
              shoeSize: (float) ss;
    
    @end
    

    然后在Thingie.m中实现协议和.h文件定义的方法:

    //Thingie.m
    -(void) encodeWithCoder:(NSCoder *) coder
    {
        [coder encodeObject: name forKey: @"name"];
        [coder encodeInt: magicNumber forKey: @"magicNumber"];
        [coder encodeFloat: shoeSize forKey: @"shoeSize"];
        [coder encodeObject: subThingies forKey: @"subThingies"];
    }
    
    -(id) initWithCoder:(NSCoder *) decoder
    {
        if (self = [super init]) {
            self.name = [decoder decodeObjectForKey: @"name"];
            self.magicNumber = [decoder decodeIntForKey: @"magicNumber"];
            self.shoeSize = [decoder decodeFloatForKey: @"shoeSize"];
            self.subThingies = [decoder decodeObjectForKey: @"subThingies"];
        }
        return self;
    }
    

    最后在main.m文件初始化Thingie

    Thingie *thing1;
    thing1 = [[Thingie alloc] initWithName: @"Thing1" magicNumer: 42 shoeSize: 10.5];
    Thingie *another;
    another = [[Thingie alloc] initWithName: @"Thing2" magicNumer: 23 shoeSize: 13.0];
    [thing1.subThingies addObject: another];
    another = [[Thingie alloc] initWithName: @"Thing3" magicNumer: 17 shoeSize: 9.0];
    [thing1.subThingies addObject: another];
    NSLog(@"%@", thing1);
    

    3.归档与解压

    NSCoder是一个抽象类,定义一些有用的方法来在对象与NSData之间来回转换。我们使用NSCoder的两个子类NSKeyedArchiver和NSKeyedUnarchiver来对对象进行归档和解压。

    //归档
    NSData *freezeDried;
    freezeDried = [NSKeyedArchiver archivedDataWithRootObject: thing1];
    

    archivedDataWithRootObject方法编码thing1对象。过程如下:

    • 首先,它在后台创建一个NSKeyedArchiver实例
    • 然后,它将NSKeyedArchiver实例传递给对象thing1的-encodeWithCoder方法。
    • 当thing1编码自身的属性时,它可能对其他对象进行编码,例如字符串、数组以及我们可能输入到该数组中的任何内容。
    • 整个对象集合完成对键和值的编码后,具有键值对的归档程序将所有对象扁平化为一个NSData类并将其返回。
    //解压
    Thingie *thing2 = [NSKeyedUnarchiver unarchiveObjectWithData: freezeDried];
    NSLog(@"%@", thing2);
    

    三.总结

    可以采用NSCoding协议和实现方法来编码和解码对象:可以将自己的大量对象转换成NSData类,然后将它保存到磁盘中,并可以在以后读取它。通过这种NSData类,可以重新创建对象。

    相关文章

      网友评论

        本文标题:2018-05-30 文件加载与保存

        本文链接:https://www.haomeiwen.com/subject/zvgtsftx.html