1

I'm attempting to build an app which will track a route, then store the route in parse.com so I can overlay the route taken by a user using MKpolyline.

I'm very new to Objective-c and IOS development, so please excuse my ignorance!!

I'm stuck when I try to save the route taken, then send/save the location array so I can rebuild the MKpolyline on the next view controller which is opened when the user completes the activity.

I'm not sure whether to save the location array to NSUserDefaults or save it to core data. At the moment I am converting the Array to an NSValue and the saving it to NSUserDefaults like so:

 count = [self.locations count];

        CLLocationCoordinate2D coordinates[count];
        for (NSInteger i = 0; i < count; i++) {
            coordinates[i] = [(CLLocation *)self.locations[i] coordinate];
            NSValue *locationValue = [NSValue valueWithMKCoordinate:coordinates[i]];
            [_locationsArray addObject:locationValue];




 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    [defaults setObject:totalDistance forKey:@"totalDistance"];
    [defaults setObject:_locationsArray forKey:@"mapOverlay"];
   // [defaults setDouble:_totalTime forKey:@"totalTime"];
    [defaults setObject:avgSpeedToBeSaved forKey:@"averageSpeed"];
    [defaults setObject:totalCalories forKey:@"totalCalories"];

    [defaults synchronize];

Is this the right way to do this? And how do I rebuild the locations Array.

If anyone could point me in the right direction it would be greatly appreciated.

I've now changed my code to what was suggested by manecosta to rebuild the CLLocationCoordinates to create an MKPolyline, but my issue now is that the array is Null from where I start to convert into an NSValue. I am unable to figure out why this is, is there something wrong with the way I'm building LocationsArray in the first place?

Khledon
  • 193
  • 5
  • 23
  • Have you tried just reading the object from userDefaults with `objectForKey:`? the array will be recreated appropriately. – Merlevede Feb 27 '14 at 19:58
  • @Merlevede Won't I need Coordinates to build an MKPolyline? rather than NSValues? Thanks – Khledon Feb 27 '14 at 20:19

2 Answers2

1

Yes, I guess you're doing it right and to rebuild just do the opposite, which should be something like:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSArray *locationsArray = [defaults objectForKey:@"mapOverlay"];

CLLocationCoordinate2D coordinates[[locationsArray count]];
NSInteger i = 0;
for(NSValue *locationValue in locationsArray){
    coordinates[i] = [locationValue MKCoordinateValue];
    i++;
}

About the fact that you're using User Defaults to store tons of data. I don't really know what is correct, but I'll tell you that I've previously used it to store the cache of my app which were quite big arrays and dictionaries and it never failed me.

manecosta
  • 8,682
  • 3
  • 26
  • 39
  • Thanks for this I thought this would deb the solution, but I get an error - thread 1: EXC_BAD_ACCESS(code=1, address=0x9c6dd7498 – Khledon Feb 27 '14 at 20:40
  • I've did an NSLog on the locations array before it is saved to NSUserDefaults and it is NULL am I maybe doing something I may have done wrong when I conveyed locationsArray to NSVales? – Khledon Feb 27 '14 at 21:03
0

You can get object from NSUserDefaults by using objectForKey:

As you have [defaults setObject:totalDistance forKey:@"totalDistance"];.

Now if you want to get the totalDistance back from the NSUserDefaults` then you can use following code:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *arrayLocation = [defaults objectForKey:@"totalDistance"];

But a piece of advise for you is not to use NSUserDefaults for your project. NSUserDefaults should only be used to store little amount of data (It's just a personal opinion.). Your locationArray is going to be quite large. Right?

A nice comparison between the two options NSUserDefaults & CoreData What are the limitations of NSUserDefaults?

I'm posting answer here (from above link - in case the question gets unavailable in future time - who knows !!)

NSUserDefaults offers a trivial learning curve and thread safe implementation.

Otherwise I've found Core Data superior in every way. Especially with regards to configuring default values and migration routines.

EDIT: I actually haven't tried but it seems to be this way.. Tell me if it does not work.

To get back NSArray from NSValue

NSValue *value = [defaults objectForKey:@"mapOverlay"];
NSArray *arrayTemp;
[value getValue:&arrayTemp];
Community
  • 1
  • 1
Akshit Zaveri
  • 4,166
  • 6
  • 30
  • 59
  • 2
    That information about NSUserDefaults is incorrect. It does not use the main thread. Most likely, they called synchronize on the main thread themselves (in most situations there's no need to call synchronize at all). – Catfish_Man Feb 27 '14 at 20:22
  • @Akshit Zaveri Yeah I figured NSUserDefaults should only by used for small data, as the location array could potentially be quite large! But the problem I'm having is that I can't save a CLLocations array to NSUserDefaults as its a struct? So I converted it to an NSValue, but I'm not sure how I would get the coordinates back to rebuild my MKpolyline overlay. – Khledon Feb 27 '14 at 20:26
  • @user3254994,, Try this -> `NSValue *value = [defaults objectForKey:@"mapOverlay"]; NSArray *arrayTemp; [value getValue:&arrayTemp];` – Akshit Zaveri Feb 27 '14 at 20:34
  • I absolutely trust him. That's y i removed the incorrect info from my answer.& voted his comment too.. @Zaph – Akshit Zaveri Feb 27 '14 at 20:46
  • 1
    The reason I say most situations, is that there are a few places left where it's useful :) I'll elaborate on those in case anyone cares. 1) To pick up changes from outside your process (such as changes made in Settings). 2) To persist data immediately instead of in a few seconds. The biggest place this is useful is when developing, since "stop" in Xcode is basically the same as crashing your app. However, even outside of Xcode, if the user launches a huge game, your app might get killed due to being out of memory. If it's not one of those though, it won't fix anything. – Catfish_Man Feb 27 '14 at 23:45