Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

Saving a class in nsuserdefaults?

jyujyu Posts: 19Registered Users
edited August 2011 in iPhone SDK Development
in my app, im trying to create it so that whenever the user adds a new entry into the tableview, it creates a new instance of a class. And that is added into an nsmutablearray. But I'm having problems saving that information.

is there any way to save and load a nsmutablearray of classes into nsuserdefaults?

I tried briefly to convert it to nsdata but it didn't work.

I tried nsarchiver. I'm not really sure on how to use it but my program crashes with
"encodeObject:forKey: only defined for abstract class. Define -[NSArchiver encodeObject:forKey:"

I'm kinda lost on what to do. help is greatly appreciated.. :)

here's some of my code.
- (void)addNewEntry {

	MyClass *myclass =[[MyClass alloc] init];
	[myMutableArray insertObject: myclass atIndex:0];
	[self.tableView reloadData];
	[NSArchiver archiveRootObject:myMutableArray toFile:@"array"];
//obviously this part doesnt work
//	[[NSUserDefaults standardUserDefaults] setObject:myMutableArray forKey:@"array"];
}
Post edited by jyu on

Replies

  • smithdale87smithdale87 Posts: 4,431iPhone Dev SDK Supporter @ @ @ @ @
    edited April 2009
    just search this forum for "Saving custom objects in nsuserdefaults"
  • jyujyu Posts: 19Registered Users
    edited April 2009
    just search this forum for "Saving custom objects in nsuserdefaults"

    your thread did not really explain much. ):
  • smithdale87smithdale87 Posts: 4,431iPhone Dev SDK Supporter @ @ @ @ @
    edited April 2009
    fine, you win :-D

    Your custom object needs to implement the NSCoding protocol.

    Heres an example of a custom class that has a few properties that I want to encode.
    - (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;
    }
    
    

    Now here's how you read/write from nsuserdefaults
    -(void)saveCustomObject:(MyCustomObject*)obj
    {
    	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:obj];
    
    
    	[defaults setObject:myEncodedObject forKey:@"myEncodedObjectKey"];
    }
    
    -(MyCustomObject*)loadCustomObjectWithKey:(NSString*)key
    {
        NSUserDefaults defaults = [NSUserDefaults standardUserDefaults];
        NSData *myEncodedObject = [defaults objectForKey: key];
        MyCustomObject* obj = (MyCustomObject*)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
        return obj;
    }
    

    Hope this helps
  • jyujyu Posts: 19Registered Users
    edited April 2009
    hmm.. i don't think i understand it totally.

    i have an nsmutablearray of custom classes which i wanna save. Correct me if im wrong, I'm suppose to encode the class 1st then archive the array yes?

    and am I suppose to encode the var in the class or can i just encode the class itself?

    Do i have to encode every var?

    And within the class i have another classs, do i encode that class or the var in that class too?


    sorry for all the questions. never used this before and its getting me real confused. :(
  • smithdale87smithdale87 Posts: 4,431iPhone Dev SDK Supporter @ @ @ @ @
    edited April 2009
    jyu wrote: »
    hmm.. i don't think i understand it totally.

    i have an nsmutablearray of custom classes which i wanna save. Correct me if im wrong, I'm suppose to encode the class 1st then archive the array yes?

    and am I suppose to encode the var in the class or can i just encode the class itself?

    Do i have to encode every var?

    And within the class i have another classs, do i encode that class or the var in that class too?


    sorry for all the questions. never used this before and its getting me real confused. :(

    for encoding an array of your class,

    create a new array, encode each object in the old array and add it to the new array. Then save the new array.

    Encode all the vars in the class that you want to save. I suggest all class variables and properties.

    If you have another class inside the encoded class, then that class needs to implement the NSCoding protocol as well.
  • giginhogiginho Posts: 4New Users
    edited October 2009
    for encoding an array of your class,

    create a new array, encode each object in the old array and add it to the new array. Then save the new array.

    Hi!

    I have the following case:

    - (void)encodeWithCoder: (NSCoder *)encoder
    {
    // Location* location -> simple custom object that implements coding protocol
    [encoder encodeObject: location forKey: @"location"];

    // paths = NSMutableArray of Location*
    [encoder encodeObject: paths forKey:@"paths"]; // will it work?
    }

    You said that I have to encode each object of the "paths" array and then add it to a new array, how can I do that? It seems that to encode you have to use the "encoder" object, but I don't think I can use it to encode each object of the array, just the array itself.

    Thanks!
  • smithdale87smithdale87 Posts: 4,431iPhone Dev SDK Supporter @ @ @ @ @
    edited October 2009
    You said you're Location object already conforms to NSCoding, so to save an array of Location, all you should have to do is something like this:
    // Save data if appropriate
    111	        NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    112	       
    113	        NSMutableArray *locationData = [[NSMutableArray alloc] init];
    114	        for( Location *loc in locationArray)
    115	        {
    116	        
    117	                [locationData addObject: [NSKeyedArchiver archivedDataWithRootObject:loc]];
    118	        }
    119	       
    125	        [def setObject:locationData forKey:@"kLocationArray"];
    

    and to read the array from NSUSerdefaults
     NSMutableArray *locations = [NSMutableArary array];
    NSArray *oldLocations = [[NSUserDefaults standardUserDefaults] arrayForKey:@"kLocationArray"];
    82	        if( locations )
    83	        {
    84	                //NSLog(@"locations is not nil");
    85	                for( NSData *data in oldLocations )
    86	                {
    88	                        Location* loc = (Location*) [NSKeyedUnarchiver unarchiveObjectWithData:data];
    89	                        [locations addObject:loc];
    91	                }
    92	        }
    
  • alex_ivanovalex_ivanov Posts: 41Registered Users
    edited October 2009
    Ok, great! Thank you!
    What about the case when I have several arrays of custom objects like before
    and I want to save an array of (arrays of custom objects)?

    locationData is the array of custom objects, generated like you previously said.

    Then can I do sometihing like this:
    NSMutableArray *toplevelarrayData = [[NSMutableArray alloc] init];
    [toplevelarrayData addObject: [NSKeyedArchiver archivedDataWithRootObject:locationData]];
    [toplevelarrayData addObject: [NSKeyedArchiver archivedDataWithRootObject:locationData2]];

    [[NSUserDefaults standardUserDefaults] setObject:toplevelarrayData forKey:@"toplevelarrayData"];

    It didn't work on my first try...
  • smithdale87smithdale87 Posts: 4,431iPhone Dev SDK Supporter @ @ @ @ @
    edited October 2009
    It didn't work on my first try...
    Its hard to refrain from saying something bad about this comment, but I'll try.


    Anyways, can you post ALL of the code where you're saving to and restoring from NSUSerDefaults. Which part doesnt work -- the saving, or the restoring?
  • alex_ivanovalex_ivanov Posts: 41Registered Users
    edited October 2009
    Its hard to refrain from saying something bad about this comment, but I'll try.

    Actually it worked on my second try :)
    Sorry, but when I posted the message I wasn't sure I was on the right track.
    The problem was that I didn't retained an object returned by an Unarchiver function and bad things happened.

    Thank you very much for your help!
  • MobileSoulMobileSoul Posts: 7New Users
    edited August 2011
    Sample Code give in THIS article I think will really useful. It gives a real short implementation of this technique.
Sign In or Register to comment.