6

I have an array of CLLocation data that I would like to archive. Should the NSUserDefaults system be used? Otherwise, how best to archive the CLLocation data?

petert
  • 6,672
  • 3
  • 38
  • 46
devonsmith
  • 123
  • 2
  • 11
  • If using Core Data, see this post for help: http://stackoverflow.com/questions/3797128/how-to-store-cllocation-using-core-data-iphone – petert Mar 10 '11 at 13:18

4 Answers4

15

To correctly store a CLLocation without loss of information, use an NSKeyedArchiver like this:

CLLocation *myLocationToStore = ...; // (a CLLocation object)
NSData *locationData = [NSKeyedArchiver archivedDataWithRootObject:myLocationToStore];

This can then be archived to NSUserDefaults, and likewise decoded just as simply when you retrieve it with NSKeyedUnarchiver:

CLLocation *myStoredLocation = (CLLocation *)[NSKeyedUnarchiver unarchiveObjectWithData:locationData];

The Swift equivalent functions are:

class func archivedDataWithRootObject(_ rootObject: AnyObject) -> NSData]
class func unarchiveObjectWithData(_ data: NSData) -> AnyObject?
Duncan Babbage
  • 19,972
  • 4
  • 56
  • 93
  • thanks a lot man! I was getting a "EXC_BAD_ACCESS code=1" error associated with trying to send a message to an already released object. In my case I was using dataWithBytes:length: and getBytes:length: to store/get a CLLocation object. I suspect the buffer:&locationObject was releasing it, which supplies the method with a memory address for the buffer, but when the bytes of data are copied to the buffer, the memory location pointer becomes a non Core Foundation pointer. – serge-k Jun 30 '15 at 18:55
4

UserDefaults can only store certain types of data, and should be used to store user preference information, not arbitrary application state data.

To quote the Apple docs:

The NSUserDefaults class provides a programmatic interface for interacting with the defaults system. The defaults system allows an application to customize its behavior to match a user’s preferences. For example, you can allow users to determine what units of measurement your application displays or how often documents are automatically saved.

More info here.

If your CLLocation data really does count as user preference info (which I'm not convinced of), you'll have to map the info inside CLLocation onto types that are compatible with NSUserDefaults. Read the docs for NSUserDefaults.

If your CLLocation data isn't user preference info, but just application data/state that you need to preserve, you have a few options; you could store it in core data, or you could use keyed archiving - see this tutorial, for example.

occulus
  • 16,959
  • 6
  • 53
  • 76
  • thks , but cllocation value consist of 2 double values for lat long how do i encode it, . – devonsmith Mar 11 '11 at 10:56
  • Well where do you intend to encode it to? Please accept some of the many answers people have given you and I'll write back later. – occulus Mar 14 '11 at 17:25
  • thks found out the solution using nsarchiver as you said it worked like charm thanks, also i divided cllocation2d values ,into lat and long while encoding and recreated it while decoding thanks – devonsmith Apr 29 '11 at 08:37
1

This is the usual method.

CLLocation *myLocationToStore = ...; // (a CLLocation object)
NSData *locationData = [NSKeyedArchiver archivedDataWithRootObject:myLocationToStore];
pringi
  • 3,987
  • 5
  • 35
  • 45
Kevin XU
  • 11
  • 2
1

Found out the solution using nsarchiver as you said it worked like charm thanks. Here is what i did.

- (id)initWithCoder:(NSCoder *)aDecoder
{

    self.PlaceName=[aDecoder decodeObjectForKey:@"inapPlaceName"];

    float lat, long1;

    lat=[aDecoder decodeDoubleForKey:@"inapCoordinateLat"];

    long1=[aDecoder decodeDoubleForKey:@"inapCoordinateLong"];  

    //inapCoordinate=[[CLLocationCoordinate2D alloc] initWithLatitude:lat1 longitude:long1];
    CLLocationCoordinate2D new_coordinate = { lat, long1 };
    self.inapCoordinate=new_coordinate;

    return self;

}

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

    [aCoder encodeObject:PlaceName forKey:@"inapPlaceName"];

    [aCoder encodeDouble:inapCoordinate.latitude forKey:@"inapCoordinateLat"];

    [aCoder encodeDouble:inapCoordinate.longitude forKey:@"inapCoordinateLong"]; 

}
wixardy
  • 35
  • 1
  • 5
devonsmith
  • 123
  • 2
  • 11
  • 1
    Warning: this code snippet when decoding puts lat and long into `float` locals, which throws away a bunch of precision. (They're encoded and decoded correctly, but this will result in incorrect location data after the decode.) – Ben Zotto Feb 28 '13 at 23:27