Search code examples
iphoneobjective-cnsmutablearraydata-storagewritetofile

Saving NSMutableArray to the iPhone Documents Directory


I am trying to create a mutable array with objects of a custom class called Dog and save it to a file in the iPhone documents directory to be later read out of the file and back into my application. I am trying to use NSArray's writeToFile:atomically: method to accomplish this, but when I test the results of this method, it always returns a value of NO, and the file is not created, and the array is not stored. I have a few questions about this. What file format should I save my array to? What does it mean to atomically write an array to a file? How do I read out the contents of the file once the array is stored there And most importantly, why is my array not being stored into a file at the specified path? Thank you in advance and here is the code that I am using within my app's viewDidLoad method:

NSString *documentsDir = [NSSearchPathForDirectoriesInDomains
                          (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
dogFilePath = [documentsDir stringByAppendingPathComponent:@"arrayDogsFile.plist"];
NSFileManager *fileManager = [[NSFileManager alloc] init];

NSLog(@"%@",dogFilePath);

Dog *dog1 = [[Dog alloc] init];
dog1.name = @"Dog1";
Dog *dog2 = [[Dog alloc] init];
dog2.name = @"Dog2";
Dog *dog3 = [[Dog alloc] init];
dog3.name = @"Dog3";

NSMutableArray *arrayDogs = [NSMutableArray array];
[arrayDogs addObject: dog1];
[arrayDogs addObject: dog2];
[arrayDogs addObject: dog3];

//Sorts the array in alphabetical order according to name – compareDogNames: is defined in the Dog class
arrayDogs = (NSMutableArray *)[arrayDogs sortedArrayUsingSelector:@selector(compareDogNames:)];


if ([arrayDogs writeToFile:dogFilePath atomically:YES])
    NSLog(@"Data writing successful");
else
    NSLog(@"Data writing unsuccessful");

Solution

  • You can not save your array of objects because objects are not NSString, NSData, NSArray, or NSDictionary.You could rather use NSKeyArchiver and NSKeyUnArchiver
    For example:
    #import "Foundation/Foundation.h"

    @interface Dog : NSObject {**NSCoding**}//your class must conform to NSCoding Protocol  
    @property (retain) NSString *Name;  
    @end
    

    The implementation needs some additional code. We need to implement the NSCoding protocol, which means two additional methods. (initWithCoder: and encodeWithCoder:)
    #import "Dog.h"

    @implementation Dog 
    @synthesize Name;  
    -(id)initWithCoder:(NSCoder*)decoder{    
        if ((self = [super init])) {  
            Name = [decoder decodeObjectForKey:@"Name"];  
    }  
        return self;  
    }
    
    
    
    -(void)encodeWithCoder:(NSCoder*)encoder{  
        [encoder encodeObject:Name forKey:@"Name"];  
    } 
    

    Once we implement the protocol, saving will look like this:
    // Save method
    // We initialise our object and set the values

    Dog *dog1 = [[Dog alloc] init];  
    dog1.Name= @"Dog1";  
    Dog *dog2 = [[Dog alloc] init];  
    dog2.Name= @"Dog2";  
    Dog *dog3 = [[Dog alloc] init];  
    dog3.Name= @"Dog3";    
    NSMutableArray *arrayDogs = [NSMutableArray array];  
    [arrayDogs addObject: dog1];  
    [arrayDogs addObject: dog2];  
    [arrayDogs addObject: dog3];  
    

    //Sorts the array in alphabetical order according to name – compareDogNames: is defined in the Dog class

    arrayDogs = (NSMutableArray *)[arrayDogs sortedArrayUsingSelector:@selector(compareDogNames:)];  
    

    // Store the array

    [NSKeyedArchiver archiveRootObject:arrayDogs toFile:dogFilePath];  
    

    //load the array*

    NSMutableArray* retreivedADogObjs = [NSKeyedUnarchiver unarchiveObjectWithFile:dogFilePath]; 
    @end  
    

    Hope it will help you
    Happy to help.*