Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone / Objective-C: NSMutableArray writeToFile won't write to file. Always returns NO

I'm trying to serialize two NSMutableArrays of NSObjects that implement the NSCoding protocol. However it works for one (stacks) and not the other (cards). I have the following block of code:

-(void) saveCards
{
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString* documentsDirectory = [paths objectAtIndex:0];

    NSString* cardsFile = [documentsDirectory stringByAppendingPathComponent:@"cards.state"];
    NSString* stacksFile = [documentsDirectory stringByAppendingPathComponent:@"stacks.state"];
    BOOL c = [rootStack.cards writeToFile:cardsFile atomically:YES];
    BOOL s = [rootStack.stacks writeToFile:stacksFile atomically:YES];
}

I step through this method using the debugger, and after the last two lines of code run, I check the values of the two BOOLs. BOOL c is NO and BOOL s is YES. The stacks array is actually empty (which is probably why it works). The cards array has contents. Why is it that the array with contents is failing? I can't figure this out. I've looked through numerous threads on SOF, each of them say the problem is because the protection level of the files they were writing were preventing them from writing. This is not my problem, as I'm writing to the Documents folder. I've double and tripple checked that neither rootStack.cards nor rootStack.stacks is nil. And I've checked that cards does indeed have content.

Here are the coder methods for my Notecard class (I added all the if statments as part of trying to solve this problem to make sure trying to encode nil values doesn't break something):

-(void) encodeWithCoder:(NSCoder *)encoder
{
    if(text)
        [encoder encodeObject:text forKey:@"text"];
    if(backText)
        [encoder encodeObject:backText forKey:@"backText"];
    if(x)
        [encoder encodeObject:x forKey:@"x"];
    if(y)
        [encoder encodeObject:y forKey:@"y"];
    if(width)
        [encoder encodeObject:width forKey:@"width"];
    if(height)
        [encoder encodeObject:height forKey:@"height"];
    if(timeCreated)
        [encoder encodeObject:timeCreated forKey:@"timeCreated"];
    if(audioManagerTicket)
        [encoder encodeObject:audioManagerTicket forKey:@"audioManagerTicket"];
    if(backgroundColor)
        [encoder encodeObject:backgroundColor forKey:@"backgroundColor"];
}

-(id) initWithCoder:(NSCoder *)decoder
{
    self = [super init];
    if(!self)
        return nil;

    self.text               = [decoder decodeObjectForKey:@"text"];
    self.backText           = [decoder decodeObjectForKey:@"backText"];
    self.x                  = [decoder decodeObjectForKey:@"x"];
    self.y                  = [decoder decodeObjectForKey:@"y"];
    self.width              = [decoder decodeObjectForKey:@"width"];
    self.height             = [decoder decodeObjectForKey:@"height"];
    self.timeCreated        = [decoder decodeObjectForKey:@"timeCreated"];
    self.audioManagerTicket = [decoder decodeObjectForKey:@"audioManagerTicket"];
    self.backgroundColor    = [decoder decodeObjectForKey:@"backgroundColor"];

    return self;
}

each field is either an NSString, NSNumber, or UIColor.

Thanks for any help

like image 449
Joel Avatar asked Dec 04 '22 12:12

Joel


1 Answers

You are confusing property lists with archiving. It is easy to do.

writeToFile:atomically: requires that the contents be property list compliant; that is, all objects in the array be an instance of one of the classes allowed in property lists (dictionaries, strings, data, arrays, etc...).

See: writeToFile:atomically:'s documentation.

What you want is NSArchiver and, more specifically, to read the archiving guide.

like image 181
bbum Avatar answered Dec 30 '22 09:12

bbum