NSUserDefaults NSObject with NSArray Object
Asked Answered
R

4

7

I am trying to save object in NSUserDefaults, went throught many questions on this site but could not resolve the issue, my NSObject has an NSMutableArray of another object. like here the main object is HotelDC and it has an array "features" an array of FeactureDC objects.

Here is my code:

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

    self.hotel_id = [decoder decodeIntegerForKey:@"hotel_id"];
    self.name = [decoder decodeObjectForKey:@"name"];
    self.features = [decoder decodeObjectForKey:@"features"];

}
return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {

[encoder encodeInt:hotel_id forKey:@"hotel_id"];
[encoder encodeObject:name forKey:@"name"];
[encoder encodeObject:features forKey:@"features"];//its a mutable array
}

how should I save it, and retrieve?? I am getting error as

 Attempt to insert non-property value '<HotelDC: 0xa600fe0>' of class 'HotelDC'. 
 Note that dictionaries and arrays in property lists must also contain only property values.

Solution :

//Setting
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:hotelObjSelected];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:myEncodedObject forKey:@"selectHotelObject"];

[[NSUserDefaults standardUserDefaults] synchronize];

// retrieving
NSData *data = [defaults objectForKey:@"selectHotelObject"];
hotelObjSelected = [NSKeyedUnarchiver unarchiveObjectWithData:data];
Reconnaissance answered 4/2, 2013 at 12:19 Comment(2)
HotelDC implements NSCoding, but what about FeatureDC?Lading
@FirozeLafeer it also implements nscodingReconnaissance
S
3

NSUserDefaults is backed by a property list. Alas, proprety lists cannot contain serialised objects. Quoting from the manual:

A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData

You'll have to create your own serialised data file for saving the object directly, or serialise the objects as one of the allowed types. Annoyingly, NSUserDefaults doesn't call encodeWithCoder - it just screens the object type passed to setObject:forKey:. The best bet is to either serialise the fields of the HotelDC yourself, or archive the object to an NSData instance and store that.

Saying answered 4/2, 2013 at 12:40 Comment(2)
As mentioned there NSArray, if i make my NSMutableArray to NSArray will it work?Reconnaissance
It's not the NSMutableArray (as that's an NSArray, it would serialise). The problem is, at some point, you're calling [nsUD setObject:someHotelDC forKey:aKey]. NSUserDefaults is too stupid to call the encodeObject method - it just checks to see if the type of someHotelDC is a known property list type. It's not, so it throws the exception. You need to wrap up the HotelDC instance in a property list type before you try to add it to the property list (encoding as NSData first would work).Saying
L
1

I have did this by following way.check it. Below code is in for loop.

 NSMutableArray *newEventArray = [[NSMutableArray alloc] init];
                    [newEventArray addObject:title];
                    [newEventArray addObject:alarmDate];

 NSArray *iCalAlarmArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"alarmList"];
                    if(iCalAlarmArray == nil || [iCalAlarmArray count] <= 0)
                    {
                        iCalAlarmArray = [[NSMutableArray alloc] init];
                    }

iCalAlarmArray = [iCalAlarmArray arrayByAddingObject:newEventArray];

[[NSUserDefaults standardUserDefaults] setObject:iCalAlarmArray forKey:@"alarmList"];

[[NSUserDefaults standardUserDefaults] synchronize];

May this helps you.

Ljubljana answered 4/2, 2013 at 13:6 Comment(0)
A
0

you should write similiar encoding and decoding methods in FeatureDC and store it in an array and then encode here.

Aeroneurosis answered 4/2, 2013 at 12:38 Comment(1)
yes i am doing the same encoding and decoding, u mean that i store object in an array and save that as NSData *data = [NSKeyedArchiver archivedDataWithRootObject:hotelObj];Reconnaissance
M
0

A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData

Myelitis answered 3/5, 2016 at 12:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.