!!!Obj-c on Mac --- Chapter 15 File Loading and Saving

本文介绍Cocoa中属性列表的应用,包括日期、数据的处理方式,以及如何使用NSArray和NSDictionary等类来读写属性列表文件。同时,深入探讨了对象编码与解码的过程,演示了如何利用NSCoding协议实现对象的持久化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Property Lists

In Cocoa, there is a class of objects known as property list objects, frequently abbreviated as plist. These lists contain a small set of objects that Cocoa knows how to do stuff with, in particular, how to save them to files and load them back. The property list classes are NSArray, NSDictionary, NSString, NSNumber, NSDate, and NSData, along with their mutable counterparts if they have any.

NSDate

To get the current date and time, use [NSDate date], which gives you an autoreleased object.

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

NSData

Cocoa provides us the NSData class that wraps a hunk of bytes. You can get the length of the data and a pointer to the start of the bytes.

NSData is an object, the usual memory management behaviors apply. So, if you’re passing a hunk of data to a function or method, you can pass an autoreleased NSData instead without worrying about cleaning it up.

const char *string = "Hi there, this is a C string!";
NSData *data = [NSData dataWithBytes: string
length: strlen(string) + 1];          // C string need to add the trailing 0
NSLog (@"data is %@", data);
// data is <48692074 68657265 2c207468 69732069 73206120 43207374 72696e67 2100>
NSData objects are immutable. Once you create them, that’s it.

Writing and Reading Property Lists

The collection property list classes (NSArray, NSDictionary) have a method called -writeToFile: atomically:, which writes the property lists to files. NSString and NSData also have a writeToFile:atomically: method, but it just writes out strings or blobs of data.

NSArray *phrase;
phrase = [NSArray arrayWithObjects: @"I", @"seem", @"to",
@"be", @"a", @"verb", nil];
[phrase writeToFile: @"/tmp/verbiage.txt" atomically: YES];
Some property list files, especially the preferences files, are stored in a compressed binary format. You can convert these files to something human-readable using the plutil command: plutil -convert xml1 filename.plist.

Encoding Objects

Cocoa has machinery for letting objects convert themselves into a format that can be saved to disk.

Objects can encode their instance variables and other data into a chunk of data, which can be saved to disk. That chunk of data can be read back into memory later, and new objects can be created based on the saved data. This process is calledencodinganddecoding, or serializationand deserialization.

@protocol NSCoding
- (void) encodeWithCoder: (NSCoder *) aCoder;
- (id) initWithCoder: (NSCoder *) aDecoder;
@end
An NSCoder is an abstract class that defines a bunch of useful methods for converting your objects into an NSData and back. You never create a new NSCoder because it doesn’t actually do much. But there are a couple of concrete subclasses of NSCoder that you actually use to encode and decode your objects.

Sample: P296

Notice that there’s a different encodeSomething:forKey: for each type. You need to make sure you use the proper method to encode your types. For any Objective-C object type, you use encodeObject:forKey:

We can put objects into the array, and they will get encoded automatically when the array gets encoded.
#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 (retain) NSMutableArray *subThingies;

- (id)initWithName: (NSString *) n
       magicNumber: (int) mn  
          shoeSize: (float) ss;

@end // Thingie

@implementation Thingie
@synthesize name;
@synthesize magicNumber;
@synthesize shoeSize;
@synthesize subThingies;

- (id)initWithName: (NSString *) n
       magicNumber: (int) mn  
          shoeSize: (float) ss
{
    if (self = [super init])
    {
        self.name = n;
        self.magicNumber = mn;
        self.shoeSize = ss;
        self.subThingies = [NSMutableArray array];
    }
    
    return (self);
}

- (void) dealloc
{
    [name release];
    [subThingies release];
    
    [super dealloc];
} // dealloc


- (void) encodeWithCoder: (NSCoder *) coder
{
    [coder encodeObject: name
                 forKey: @"name"];
    [coder encodeInt: magicNumber
              forKey: @"magicNumber"];
    [coder encodeFloat: shoeSize
                forKey: @"shoeSize"];
    [coder encodeObject: subThingies
                 forKey: @"subThingies"];
    
} // encodeWithCoder


- (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);
    
} // initWithCoder


- (NSString *) description
{
    NSString *description = 
    [NSString stringWithFormat: @"%@: %d/%.1f %@",
     name, magicNumber, shoeSize, subThingies];
    
    return (description);
    
} // description


@end // Thingie


int main (int argc, const char * argv[])
{
    @autoreleasepool
    {
        Thingie *thing1;
        thing1 = [[Thingie alloc]
                  initWithName: @"thing1"
                  magicNumber: 42
                  shoeSize: 10.5];
        
        NSLog (@"some thing: %@", thing1);
        
        NSData *freezeDried;
        freezeDried = [NSKeyedArchiver archivedDataWithRootObject: thing1];
        
        [thing1 release];
        
        thing1 = [NSKeyedUnarchiver unarchiveObjectWithData: freezeDried];
        
        NSLog (@"reconstituted thing: %@", thing1);
        
        Thingie *anotherThing;
        
        anotherThing =  [[[Thingie alloc]
                          initWithName: @"thing2"
                          magicNumber: 23
                          shoeSize: 13.0] autorelease];
        [thing1.subThingies addObject: anotherThing];
        anotherThing =  [[[Thingie alloc]
                          initWithName: @"thing3"
                          magicNumber: 17
                          shoeSize: 9.0] autorelease];
        [thing1.subThingies addObject: anotherThing];
        
        NSLog (@"thing with things: %@", thing1);
        
        freezeDried = [NSKeyedArchiver archivedDataWithRootObject: thing1];
        
        thing1 = [NSKeyedUnarchiver unarchiveObjectWithData: freezeDried];
        NSLog (@"reconstituted multithing: %@", thing1);
        
        [thing1.subThingies addObject: thing1];
        
        // You really don't want to do this...
        // NSLog (@"infinite thinging: %@", thing1);
        
        freezeDried = [NSKeyedArchiver archivedDataWithRootObject: thing1];
        
        thing1 = [NSKeyedUnarchiver unarchiveObjectWithData: freezeDried];
        
    }
    return (0);
    
} // main



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值