Will Ullrich
Will Ullrich

Reputation: 2238

Saving Custom NSArray Data to iPhone

I have been trying to save locally (through NSUserDefaults) a NSMutableArray of PFGeoPoints that a user creates. After much reading and research, I now know that simply saving an array with custom data is quite frankly impossible. I have tried the following in several different ways:

   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   NSMutableArray *testArray = [[NSMutableArray alloc] init];
   NSArray *checkArray = [[NSArray alloc] init];

   testArray = locationList;
   PFGeoPoint *test = [locationList objectAtIndex:0];
   NSString *latString = [NSString stringWithFormat:@"%f",test.latitude];
   [testArray insertObject:latString atIndex:0];

   checkArray = testArray;

   [defaults setValue:checkArray forKey:@"Locations"];
   [defaults synchronize];

where locationList is a NSMutableArray that has been created and set to PFGeoPoints from Parse.

I had also tried converting the NSMutableArray to NSData via

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];

, but this still did not work. Each time I kept receiving the error telling me the following:

Property list invalid for format: 200 
(property lists cannot contain objects of type 'CFType')

The NSMutableArray that I am saving is a list that contains multiple PFGeoPoints. All I am trying to do is save this array to the device, so that the user does not have to recreate (render) the entire list each time the user loads the application (I am using cloud data...not trying to spend too much for data).

If someone could help me out with either a suggestion/solution on how to save this data as an array (rather than breaking up each line into integers for lat and long), OR if someone can suggest a helpful alternative to NSUserDefaults (like perhaps Core Data or some other local storage) I would be most appreciative. Thanks

Upvotes: 2

Views: 484

Answers (2)

Tejas Ardeshna
Tejas Ardeshna

Reputation: 4373

simply you need to implement NSCoding protocol

Write array:

Obj-C

-(void)writeArrayWithCustomObjToUserDefaults:(NSString *)keyName withArray:(NSMutableArray *)myArray {

       NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
       NSData *data = [NSKeyedArchiver archivedDataWithRootObject:myArray];
       [defaults setObject:data forKey:keyName];
       [defaults synchronize]; 

}

Swift 2.3

func writeArrayWithCustomObjToUserDefaults(keyName: String, withArray myArray: [AnyObject]) {
    var defaults = NSUserDefaults.standardUserDefaults()
    var data = NSKeyedArchiver.archivedDataWithRootObject(myArray)
    defaults.setObject(data, forKey: keyName)
    defaults.synchronize()
}

Swift 3.1

func writeArrayWithCustomObj(toUserDefaults keyName: String, withArray myArray: [Any]) {
    let defaults = UserDefaults.standard
    let data = NSKeyedArchiver.archivedData(withRootObject: myArray)
    defaults.set(data, forKey: keyName)
    defaults.synchronize()
}

Read Array:

Obj-C

-(NSArray *)readArrayWithCustomObjFromUserDefaults:(NSString*)keyName {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [defaults objectForKey:keyName];
    NSArray *myArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    [defaults synchronize];
    return myArray;  
}

Swift 2.3

func readArrayWithCustomObjFromUserDefaults(keyName: String) -> [AnyObject] {
    var defaults = NSUserDefaults.standardUserDefaults()
    var data = defaults.objectForKey(keyName)!
    var myArray = NSKeyedUnarchiver.unarchiveObjectWithData(data)!
    defaults.synchronize()
    return myArray
}

Swift 3.1

func readArrayWithCustomObj(fromUserDefaults keyName: String) -> [Any] {
    let defaults = UserDefaults.standard
    let data: Data? = defaults.object(forKey: keyName)
    let myArray: [Any]? = NSKeyedUnarchiver.unarchiveObject(with: data!)
    defaults.synchronize()
    return myArray!
}

Upvotes: 2

Abhinav
Abhinav

Reputation: 38162

To save custom objects into user defaults, it need to conform to NSCoding protocol (objects needs to code/decode).

Your custom Objects need to implement the NSCoding protocol.

Once you followed NSCoding rules; archive & save data like this:

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:yourArray];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"Key"];

Unarchive like this:

NSArray *array= [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"Key"];

Upvotes: 2

Related Questions