2

I have an NSMutableArray *recordsArray, the keys are NSStrings, and the values are a custom object:

@interface DictRecord : NSObject{
}
@property (nonatomic, retain) NSString* word; 
@property (nonatomic, retain)  NSString  *wordStatus;

Cocoa: How to save/archive an NSMutableArray containing custom objects

I want to save that NSMutable array, preferably in a non-binary (somewhat readable) format.

I have read through the docs and have added the encoding methods to DictRecord:

- (void) encodeWithCoder: (NSCoder *)coder
{
    [coder encodeObject: _word forKey:@"word" ];
    [coder encodeObject: _wordStatus forKey:@"wordStatus" ];
}
- (id) initWithCoder: (NSCoder *) coder
{
    self = [super init];
    if (self) {
        self.word = [coder decodeObjectForKey:@"word"];
        self.wordStatus = [coder decodeObjectForKey:@"wordStatus"];
}

Then I try to save using:

[recordsArray writeToFile:filePath atomically:YES];

A file is saved, but I can see that it's empty.

Can anyone tell me which steps I have omitted, or if I've gone about it the wrong way.

Thanks

paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
Joey FourSheds
  • 479
  • 1
  • 7
  • 18

2 Answers2

5

It's a bit confusing, but NSCoding and the NSArray and NSDictionary property list methods are two separate things.

You have two choices:

  1. Use NSCoding. Here's an answer which shows how to correctly get the coding methods called on the contents of the array.
  2. Use -[NSArray writeToFile:atomically:]. Instead of implementing -initWithCoder: and -decodeWithCoder, create two methods of your own: -dictionaryValue and -initWithDictionary:. To write, iterate through the array of model objects, build a new array of dictionaries, and invoke -writeToFile:atomically: on that. To read, invoke one of the NSArray reading methods, take the dictionaries it contains, and invoke -initWithDictionary: with each one.

If you want a human-readable plist, the second option is a good choice.

Community
  • 1
  • 1
paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
  • Thanks noa, went with the 2nd method and got it working. If I understood you correctly, it was a case of completely re-building the data-structure in property-list-compkliant format. I didn't use any dictionaries though, as it seemed easier to create an NSArray for each record of 3 NSStrings ([0]=key [1]=word [2]=wordstatus), then save an array of these arrays. It's saving and loading, and is human-readable :) Would there be a benefit to using dictionaries? – Joey FourSheds Feb 12 '13 at 17:17
  • Yes: as your schema changes, your new and old data files will still make sense. If you provide default values in your initializer, the missing values can inherit the defaults. – paulmelnikow Feb 12 '13 at 21:00
1

-[NSArray writeToFile:atomically:] documentation states

This method recursively validates that all the contained objects are property list objects before writing out the file, and returns NO if all the objects are not property list objects

If you want to create a property list file and have the NSCoder stuff get called, you have to use NSKeyedArchiver/NSKeyedUnarchiver.

Ken Aspeslagh
  • 11,484
  • 2
  • 36
  • 42