Search code examples
iphoneiossmartphone

ios storing custom objects


How can I store NSMutableArray of custom objects? I have this code for loading and saving files:

- (NSMutableArray *)loadDataFromFile:(NSString *)fileName {
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docDir = [paths objectAtIndex:0];
    NSString *path = [docDir stringByAppendingPathComponent:fileName];
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    if (![fileMgr fileExistsAtPath:path]) {
        NSArray *fileArray = [fileName componentsSeparatedByString:@"."];
        NSString *name = [fileArray objectAtIndex:0];
        NSString *ext = [fileArray objectAtIndex:1];
        NSString *bundle = [[NSBundle mainBundle] pathForResource:name ofType:ext];
        [fileMgr copyItemAtPath:bundle toPath:path error:&error];
    }
    NSMutableArray *data = [[NSMutableArray alloc] initWithContentsOfFile:path];
    return data;
}

- (void)saveData:(NSMutableArray *)arrayData toFile:(NSString *)filename forKey:(NSString *)key {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docDir = [paths objectAtIndex:0];
    NSString *path = [docDir stringByAppendingPathComponent:filename];
    [arrayData writeToFile: path atomically:YES];
    NSLog(@"%@", arrayData);
}

But when I used data.plist as filename, it didn't work because NSLog(@"%@", arrayData); returns list custom object adresses:

"AreaTableRecord: 0x76a7ef0"

This custom object is inserted to array using this code:

AreaTableRecord *area=[[AreaTableRecord alloc] init];
        area.title=title;
        area.lastScore=0;
        area.vocabulary=[[NSMutableArray alloc] init];
        [self.areas addObject:area];

How could I store NSMutableArray self.areas that contains custom objects AreaTableRecord? and What file format shloud I use to store this data? (it seems to me that plist is not working in this case)


Solution

  • You are only able to store primitive data types in NSDefaults or a plist. In order to work around this you can either choose to store your information in a database....or encode your objects as byte streams and then save them into a file.

    Take a look at this thread. It details how to go about encoding your objects.

    Basically you need to add these methods to your custom class:

    - (void)encodeWithCoder:(NSCoder *)encoder
    {
           //Encode properties, other class variables, etc
        [encoder encodeObject:self.question forKey:@\"question\"];
        [encoder encodeObject:self.categoryName forKey:@\"category\"];
        [encoder encodeObject:self.subCategoryName forKey:@\"subcategory\"];
    }
    
    
    - (id)initWithCoder:(NSCoder *)decoder
    {
        self = [super init];
        if( self != nil )
        {
                   //decode properties, other class vars
            self.question = [decoder decodeObjectForKey:@\"question\"];
            self.categoryName = [decoder decodeObjectForKey:@\"category\"];
            self.subCategoryName = [decoder decodeObjectForKey:@\"subcategory\"];
        }
        return self;
    }
    

    And then in order to use them you make calls as such:

    For setting:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:obj];  
    [defaults setObject:myEncodedObject forKey:@\"myEncodedObjectKey\"];
    

    For retrieving:

    NSUserDefaults defaults = [NSUserDefaults standardUserDefaults];
    NSData *myEncodedObject = [defaults objectForKey: key];
    MyCustomObject* obj = (MyCustomObject*)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];