从零开始——我的OC学习之路

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

2018-05-30  本文已影响2人  肠粉白粥_Hoben

一.属性列表

在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.为什么要用编码?

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对象。过程如下:

//解压
Thingie *thing2 = [NSKeyedUnarchiver unarchiveObjectWithData: freezeDried];
NSLog(@"%@", thing2);

三.总结

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

上一篇下一篇

猜你喜欢

热点阅读