0

I created a custom class to display in a TableView, I read a custom class object's array in TableView. Now, when I close the app I lose my date. I want to save that data permanently. But when I try to do so, I get the following error:

Attempt to set a non-property-list object as an NSUserDefaults

My code is:

@implementation CAChallangeListViewController
- (void)loadInitialData{
    self.challangeItems = [[NSUserDefaults standardUserDefaults] objectForKey:@"challanges"];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[NSUserDefaults standardUserDefaults] setObject:self.challangeItems forKey:@"challanges"];
}

Here, the self. Challange items is a NSMutable array which contains objects of type CAChallange which is a custom class with following interface.

@interface CAChallange : NSObject
    @property NSString *itemName;
    @property BOOL *completed;
    @property (readonly) NSDate *creationDate;
@end
rmaddy
  • 314,917
  • 42
  • 532
  • 579
divyenduz
  • 2,037
  • 19
  • 38
  • possible duplicate of [Attempt to set a non-property-list object as an NSUserDefaults](http://stackoverflow.com/questions/19720611/attempt-to-set-a-non-property-list-object-as-an-nsuserdefaults) – nhgrif Nov 17 '13 at 15:52
  • 2
    conform to the NSCoding protocol and save it as NSData – Kaan Dedeoglu Nov 17 '13 at 15:52

3 Answers3

3

You can easily accomplish what you are doing by converting your object into a standard dictionary (and back when you need to read it).

NSMutableArray *itemsToSave = [NSMutableArray array];
for (CAChallange *ch in myTableItems) {
   [itemsToSave addObject:@{ @"itemName"     : ch.itemName,
                             @"completed"    : @(ch.completed),
                             @"creationDate" : ch.creationDate }];
}
Mundi
  • 79,884
  • 17
  • 117
  • 140
1

You can use NSKeyedArchiver to create an NSData representation of your object. Your class will need to conform to the NSCoding protocol, which can be a bit tedious, but the AutoCoding category can do the work for you. After adding that to your project, you can easily serialize your objects like this:

id customObject = // Your object to persist
NSData *customObjectData = [NSKeyedArchiver archivedDataWithRootObject:customObject];
[[NSUserDefaults standardUserDefaults] setObject:customObjectData forKey:@"PersistenDataKey"];

And deserialize it like this:

NSData *customObjectData = [[NSUserDefaults standardUserDefaults] objectForKey:@"PersistenDataKey"];
id customObject = [NSKeyedUnarchiver unarchiveObjectWithData:customObjectData];
Paul Hunter
  • 4,453
  • 3
  • 25
  • 31
0

Your CAChallange object has a pointer to a BOOL which is not a suitable type for a plist:-

 @property BOOL *completed

This is probably causing the error. You cannot store raw pointers in a plist.

Echelon
  • 7,306
  • 1
  • 36
  • 34
  • 1
    I think it is the `CAChallange` type the compiler objects to. Booleans are possible as NSUserDefaults. – Mundi Nov 17 '13 at 15:56