Tuesday, August 3, 2010

Storing custom object and array in NSUserDefaults

In one of my recent program I required to save application state. Easiest solution to save application state in iPhone is to use NSUserDefaults.

In my application I was creating some custom object and array which store custom object and I required to save those in NSUserDefaults

Initially I struggled with this but finally got solution, so though to share it.

First of all, if you want to save your custom object in NSUserDefaults than it should follow NSCoding protocol.

So your custom class should implement NSCoding protocol like following.

@interface MyClass : NSObject <NSCoding>{
BOOL someFlag;
}

@end

#import "MyClass.h"

@implementation MyClass

- (void) encodeWithCoder:(NSCoder *)coder 
    //uncomment following if super class is following NSCoding protocol
    //[super encodeWithCoder:coder];
    [coder encodeBool:someFlag forKey:@"SomeFlag"];
}

- (id) initWithCoder:(NSCoder *)coder 
{
    //uncomment following if super class is following NSCoding protocol
    //self = [super initWithCoder:coder];
    self = [super init];
    if( self
    {         
        someFlag = [coder decodeBoolForKey:@"SomeFlag"];
    }    
    return self;
}

@end

Now to store and restore above defined custom class in NSUserDefaults, we can use following code as shown in saveState and restoreState function.

#import "MyClass.h"

@interface Controller : NSObject {
    MyClass* myClass;
    NSMutableArray* myClassArray
    int currentState;
}

- (void) saveState;

- (void) restoreState;

@end

#import "Controller.h"

@implementation Controller

- (void) saveState 
{    
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    
    NSData* myClassData = [NSKeyedArchiver archivedDataWithRootObject:myClass];
    [defaults setObject:myClassData forKey:@"MyClass"];
    
    NSData* myClassArrayData = [NSKeyedArchiver archivedDataWithRootObject:myClassArray];
    [defaults setObject:myClassArrayData forKey:@"MyClassArray"];
    
    [defaults setInteger:currentState forKey:@"CurrentState"];
}

- (void) restoreState 
{    
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    
    NSData* myClassData = [defaults objectForKey:@"MyClass"];
    myClass = [NSKeyedUnarchiver unarchiveObjectWithData:myClassData];
    
    NSData* myClassArrayData = [defaults objectForKey:@"MyClassArray"];    
    NSArray *savedMyClassArray = [NSKeyedUnarchiver unarchiveObjectWithData:myClassArrayData];
    if( savedMyClassArray != nil
        myClassArray = [[NSMutableArray alloc] initWithArray:savedMyClassArray];
   else
myClassArray =  [[NSMutableArray alloc] init];
    
    currentState = [defaults integerForKey:@"CurrentState"];
}

@end

3 comments:

  1. Hey,

    I need help. I've managed to put your code working, its saves all the objects into the array, nice !! But when i try to use them, its possible to see how many objects the array has but all the object are out of scope ! what am i missing ? any ideias ?

    Thanks

    ReplyDelete
  2. I am not sure until you give me you code where you save and restore your array. For me above code works fine, its from my working application.But if you are storing custom class in array then check if you are supporting NSCoding protocol properly.

    ReplyDelete