Reputation: 1359
I have a pretty straightforward implementation of CLLocationManager. It collects user coords and when data is of appropriate distance and accuracy it sends to my server. However, sometimes there is no network connectivity. In these cases, I need to store the data locally and rePOST to my server when connection returns. How do I,
A: store and retrieve the data locally?
B: instruct CLLocationManager to resend when connectivity returns?
Wrinkle: I am collecting data continuously on a moving target, so I may need to store several or many coords in an Array until network connection returns. Further wrinkle: I am very new to iOS dev :)
What I believe is the relevant part of my code:
NetworkStatus internetStatus = [[Reachability reachabilityForInternetConnection] currentReachabilityStatus];
if( internetStatus != NotReachable ) {
NSData* data = [NSURLConnection sendSynchronousRequest:post returningResponse:response error:error];
if( data == nil ) {
NSLog( @"Doh!" );
}
else {
NSLog(@"Data sent! %@", data);
}
}
else {
NSLog(@"No connection");
}
Magic needs to happen in that last else
Any takers? Thanks!
Upvotes: 0
Views: 256
Reputation: 2431
If all you want to store is just the coordinates, then I think NSUserDefaults
would be the easiest solution to implement. There are a few different approaches that would work, here's one that stores all of the coordinates as a string separated by ;
for pairs of coordinates and ,
between longitude and lattitude.
- (void)saveCoordinate:(CLLocationCoordinate2D)coordinate {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *previousCoordinatesString = [defaults objectForKey:@"previousCoordinates"];
NSString *newCoordinatesString;
// check to see if the string has ever been saved for that key
if (previousCoordinatesString) {
newCoordinatesString = [NSString stringWithFormat:@"%@;%f,%f", previousCoordinatesString, coordinate.latitude, coordinate.longitude];
}
else {
newCoordinatesString = [NSString stringWithFormat:@"%f,%f", coordinate.latitude, coordinate.longitude];
}
[defaults setObject:newCoordinatesString forKey:@"previousCoordinates"];
}
To fetch the coordinates that have been saved, fetch the string from NSUserDefaults
and then parse out each coordinate pair. If there's nothing in user defaults then return NO
. Once each coordinate has been parsed, send it to the server. If the device is offline then save the string for later.
- (BOOL)fetchCoordinates {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *previousCoordinatesString = [defaults objectForKey:@"previousCoordinates"];
// check to make sure the string exists
if (!previousCoordinatesString) return NO;
NSArray *coordinateStringsArray = [previousCoordinatesString componentsSeparatedByString:@";"];
NSMutableString *coordinatesToSave = [[NSMutableString alloc] init];
for (NSString *coordinateString in coordinateStringsArray) {
NSArray *coordinatesArray = [coordinateString componentsSeparatedByString:@","];
if (coordinatesArray.count > 1) {
float lattitude = [[coordinatesArray objectAtIndex:0] floatValue];
float longitude = [[coordinatesArray objectAtIndex:1] floatValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(lattitude, longitude);
if (![self sendCoordinatesToServer:coordinate]) {
[coordinatesToSave appendFormat:@";%f,%f", lattitude, longitude];
}
}
}
if (coordinatesToSave.length > 0) {
[defaults setObject:coordinatesToSave forKey:@"previousCoordinates"];
return YES;
}
return NO;
}
- (BOOL)sendCoordinatesToServer:(CLLocationCoordinate2D)coordinate {
if (/*check for network connection*/) {
// send to server
return YES;
}
return NO;
}
The reason for breaking apart each coordinate and attempting to send it separately is so that it can be processed and adapted to your specific needs, but if an entire set of coordinates could be sent as a string at once then that would be a much better option from a mobile perspective.
Upvotes: 0
Reputation: 14154
It sounds like you should have some other way of controlling when you send the data rather than leaving it in the hands of your location manager. You could push off the work from the CLLocationManager to some other method set on a timer or notification when there is work to do.
Upvotes: 0
Reputation: 113747
The GPS will work without network, so you could store each location update you received. The best way to do this is in an SQLite database, with an id, latitude (double), longitude and timestamp. You might want some way to differentiate between sessions so you can store each as a path. You might want a flag to say "already sent this location to the server".
You could use an array, but you'd have to save it. You do this by writing a plist from the array. The SQLite approach is more robust.
This approach will work best on devices with a GPS chip (iPhones, some iPads). It usually won't work as well on Touches or WiFi iPads (they don't need connectivity, but they do need WiFi routers to be around to work).
Upvotes: 1