0

I encountered a behavior that wasn't familiar.

I searched on the Internet, and more precisely on StackOverflow, and found a lot of articles and posts about readonly properties.

I feel like there is a massive and invisible learning experience concerning compilation process and assignment/declaration/initialization.

I really want to clearly understand those situations.

Imagine I have a property

@property (nonatomic, strong) CLLocation *location;

I have stored in my NSUserDefault the last known user location as a String.

If I want to set the coordinate of my location property with my lastLocation I have a compilation error :

Assignment to readonly property

Here is my line of code :

_location.coordinate = [[MyCustomUserDefaults lastLocation] doubleValue];

Here is my NSUserDefaults getter :

 +(NSString *) lastLocation
{
    return [[NSUserDefaults standardUserDefaults] objectForKey:USER_PREF_LAST_LOCATION];
}
  • Check below link it may be useful to you http://stackoverflow.com/a/18910891 – Rajesh Dharani Apr 05 '17 at 13:47
  • Best answer in that dup, IMO, is http://stackoverflow.com/a/18910861/294949 – danh Apr 05 '17 at 13:48
  • 1
    @danh I disagree. The accepted answer is better. It scares me to see the _bytes_ of the struct saved off. Why not just save the primitive doubles? What if the `CLLocationCoordinate2D` is ever updated to use floats instead, or extra properties are added? Using the `CLLocation` initializer that accepts two specific types is much safer and future-proof. – Craig Otis Apr 05 '17 at 13:54
  • @CraigOtis *there are* several other properties currently, beyond just the coordinates. That's why I prefer the NSData idea: not to be future-proof, but to be present-proof :-) – danh Apr 05 '17 at 13:58
  • @danh Private/internal properties aside from the lat/lon? I can't see the argument for wanting to save off those properties when there's an initializer that accepts the two it actually needs. What if you've saved that data off, the user upgrades their device software, and your from-byte construction now fails? The whole benefit of the initializer/API is so the internal structure/implementation can change without outside callers needing to know. – Craig Otis Apr 05 '17 at 14:06
  • @CraigOtis the OP is saving a CLLocation object (https://developer.apple.com/reference/corelocation/cllocation#main), not merely a 2 coordinate struct. – danh Apr 05 '17 at 14:22
  • And @CraigOtis, here's how I'd handle a LC2D coordinate struct: `[NSValue value:&myLC2Dstruct withObjCType:@encode(CLLocationCoordinate2D)]`. I'm 100% with you on respecting an object's integrity (even if it's a 2nd class citizen like a struct), that's why I'm a little allergic to breaking up an object (or a struct) into multiple components (even if they are parametric) for serialization. – danh Apr 05 '17 at 14:32
  • Can someone write an answer, it's getting messy in comments here. –  Apr 05 '17 at 14:35
  • @danh Right, but that answer is saving the coordinate struct - saving the object's memory structure to disk seems less safe. If you wanted to use `NSSecureCoding` (which `CLLocation` implements) then sure, but writing bytes from disk into a pointer that has likely changed over time, seems really risky. Keep in mind `NSUserDefaults` is for longer-term storage, not just a single run of the application. You have to admit - if a user is running iOS 7, saves a `CLLocation` to defaults, then reloads it on iOS 8 - there's a solid chance it will fail at runtime - the initializer will not. – Craig Otis Apr 05 '17 at 14:35
  • @RaphaelP. Since the question was marked as a dupe, you should be able to find your answer in the referenced pages. – Craig Otis Apr 05 '17 at 14:36

2 Answers2

0

Coordinate property for CLLocation is an CLLocationCoordinate2D object. You have to initiate it like

CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);

and you can save your latitude and longitude values with using NSNumber

[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:0.5] forKey:@"latitude"];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:0.5] forKey:@"longitude"];

than you get values

double latitude = [[[NSUserDefaults standardUserDefaults] objectForKey:@"latitude"] doubleValue];
double longitude = [[[NSUserDefaults standardUserDefaults] objectForKey:@"longitude"] doubleValue];
abdullahselek
  • 7,893
  • 3
  • 50
  • 40
0

Save location coordinate in NSUserDefaults

 NSString *strlat = location.coordinate.latitude
 NSString *strlong = location.coordinate.longitude 
[[NSUserDefaults standardUserDefaults]setObject:strlat forKey:@"lat"];
[[NSUserDefaults standardUserDefaults] strlong:strlat forKey:@"long"];     
Lalit kumar
  • 1,797
  • 1
  • 8
  • 14