Google Places API returning no results? - ios

I am following this tutorial : http://www.raywenderlich.com/13160/using-the-google-places-api-with-mapkit , but for some reason my app is returning:
Google Data: (
)
Here is my .h file:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define kGOOGLE_API_KEY #"API PLACED HERE, LEFT BLANK FOR STACKOVERFLOW"
#interface ViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
CLLocationCoordinate2D currentCentre;
int currenDist;
}
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#end
and my implementation file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Make this controller the delegate for the map view.
self.mapView.delegate = self;
// Ensure that you can view your own location in the map view.
[self.mapView setShowsUserLocation:YES];
//Instantiate a location object.
locationManager = [[CLLocationManager alloc] init];
//Make this controller the delegate for the location manager.
[locationManager setDelegate:self];
//Set some parameters for the location object.
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)toolBarButtonPress:(UIBarButtonItem *)sender {
UIBarButtonItem *button = (UIBarButtonItem *)sender;
NSString *buttonTitle = [button.title lowercaseString];
[self queryGooglePlaces:buttonTitle];
}
-(void) queryGooglePlaces: (NSString *) googleType {
NSString *url = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json? location=%f,%f&radius=%#&types=%#&sensor=true&key=%#", currentCentre.latitude, currentCentre.longitude, [NSString stringWithFormat:#"%i", currenDist], googleType, kGOOGLE_API_KEY];
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", url);
//Formulate the string as a URL object.
NSURL *googleRequestURL=[NSURL URLWithString:url];
// Retrieve the results of the URL.
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
-(void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
//The results from Google will be an array obtained from the NSDictionary object with the key "results".
NSArray* places = [json objectForKey:#"results"];
//Write out the data to the console.
NSLog(#"Google Data: %#", places);
}
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
//Get the east and west points on the map so you can calculate the distance (zoom level) of the current map view.
MKMapRect mRect = self.mapView.visibleMapRect;
MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect));
MKMapPoint westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect));
//Set your current distance instance variable.
currenDist = MKMetersBetweenMapPoints(eastMapPoint, westMapPoint);
//Set your current center point on the map instance variable.
currentCentre = self.mapView.centerCoordinate;
}
#pragma mark - MKMapViewDelegate methods.
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views {
MKCoordinateRegion region;
region = MKCoordinateRegionMakeWithDistance(locationManager.location.coordinate,1000,1000);
[mv setRegion:region animated:YES];
}
#end
My console log of the final formatted URL is :
https://maps.googleapis.com/maps/api/place/search/json? location=HIDDENLAT,HIDDENLONG&radius=995&types=bar&sensor=true&key=HIDDENAPI
I have replaced the generated lat, long and API values above but they were returned as the correct values?
Another SO answer i found said to add the:
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
which I did but this has not worked for me??
Any ideas why this isnt working!? Im pulling my hair out trying to sus it out!
Thank you!

For future answer-seekers, this could be a number of issues including your API key, your search radius, or your search "type", or a JSON parsing problem. However, the code should go exactly as Gary Stewart has it posted above. He even helped me find my answer just by asking the question...
Add NSLog(#"%#", url); after the URL string in the queryGooglePlaces methord as he does above. This logs the URL request to your console so you can ensure it's being compiled as expected. If it is but you're STILL not getting data back, then copy the URL you generated from your console and open it in a web browser. At the bottom of the generated page, it will tell you why you're not getting data.
From Google's Developer Documentation:
The "status" field within the search response object contains the
status of the request, and may contain debugging information to help
you track down why the request failed. The "status" field may contain
the following values:
OK indicates that no errors occurred; the place was successfully
detected and at least one result was returned. ZERO_RESULTS indicates
that the search was successful but returned no results. This may occur
if the search was passed a latlng in a remote location.
OVER_QUERY_LIMIT indicates that you are over your quota.
REQUEST_DENIED indicates that your request was denied, generally
because of lack of a sensor parameter. INVALID_REQUEST generally
indicates that a required query parameter (location or radius) is
missing.
My problem was that I was sending a search "type" of "breakfast" rather than simply "food". Silly me, "breakfast" would be a keyword, not a type.
(Here's a list of supported types by the way: https://developers.google.com/places/documentation/supported_types)
Hope this helps uncover your problem. Best of luck!

Change
#"https://maps.googleapis.com/maps/api/place/search/json? location=%f,%f&radius=%#&types=%#&sensor=true&key=%#"
to
#"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=%#&types=%#&sensor=true&key=%#"
(ie, no space after the ? in the url template string)

Related

store key/value in NSDictionary/NSCache which retains data till the app is terminated

I have an app where i want to create a temporary cache which stores key and value.I have done the following
My code is : IN appDelegate.h
#property (strong, nonatomic) NSMutableDictionary *articleCache;
In appDelegate.m
#synthesize articleCache;
and i am calling it in viewController.m
here i need to store the data so that it is cleared only when the app is terminated and is accessible anywhere in the app otherwise.
every time i visit an article i add it to the array so that next time i wont have to fetch it from the network thereby speed up the process.
the Problem is when i set the temp NSMutableDictionary the content gets added but for checkCache.articleCache i get nil.
#define DELEGATE ((AppDelegate*)[[UIApplication sharedApplication]delegate])
this is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//[self loadfeeds];
[self.activityIndi startAnimating];
AppDelegate *checkCache = DELEGATE;
NSString *link = self.webUrl;
//check if the article is already opened and cached before
if([[checkCache.articleCache allKeys] containsObject:link])
{
NSLog(#"Key Exists");
NSString *contents = [checkCache.articleCache valueForKey:link];
[self loadDataOnView:contents];
}
else
{
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
[aQueue addOperationWithBlock:^{
NSLog(#"Key not Exists");
[self startParsing];
}];
}
}
In parser method at the end i do the following i.e to store the article..
but if i add it directly to the checkCache.articleCache nothing is added what should i do?? but it gets added to temp.. do i access the articleCache incorrectly??
AppDelegate *checkCache = DELEGATE;
NSMutableDictionary *temp = [[NSMutableDictionary alloc] init];
[checkCache.articleCache setObject:Content forKey:url];
[temp setObject:Content forKey:url];
So how can i solve it??
or Suggest me how can i use NSCache for the same problem. thanks a lot.
It might be a silly question but i m quite new to ios thanks.
In App delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.articleCache = [NSMutableDictionary new];
return YES;
}
When you have to set the object in cache.
AppDelegate *checkCache = DELEGATE;
[checkCache.articleCache setObject:obj forKey:#"Key1"];
To get the object back:
AppDelegate *checkCache = DELEGATE;
id obj = [checkCache.articleCache objectForKey:#"Key1"];
Though there are better ways to get this done.

Accessing NSDictionary object outside of ASYNC callback

I am using UNIRest to make a call and return a JSON object to my app. I have it returning the proper data as a NSDictionary and it logs our perfect. I am now trying to take that data and display it inside of my view. I cannot use my dictionary outside of the callback.
I have been digging around here on StackOverflow for similar results and posts related to variables. I feel it is a scope issue with it being limited to inside of the callback block.
My header file: (UIViewController)
#property (nonatomic, strong) NSDictionary *tideData;
My implementation:
#interface TideDetailViewController ()
#end
#implementation TideDetailViewController
#synthesize tideData;
- (void)viewDidLoad {
[super viewDidLoad];
// tideData = [[NSDictionary alloc] init];
// location is working, I removed it for testing to call a static string for now
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[self.locationManager startUpdatingLocation];
NSString *locationQueryURL = #"http://api.wunderground.com/api/XXXXXXXXXXXXX/tide/geolookup/q/43.5263,-70.4975.json";
NSLog(#"%#", locationQueryURL);
[[UNIRest get:^(UNISimpleRequest *request) {
[request setUrl: locationQueryURL];
}] asJsonAsync:^(UNIHTTPJsonResponse *response, NSError *error) {
// This is the asyncronous callback block
self.code = [response code];
NSDictionary *responseHeaders = [response headers];
UNIJsonNode *body = [response body];
self.rawResults = [response rawBody];
// I tried this as self as well
tideData = [NSJSONSerialization JSONObjectWithData:self.rawResults options: 0 error: &error];
// this logs perfectly.
NSLog(#"tideData %#", tideData);
// tried setting it to the instance
//self.tideData = tideData;
}];
// returns null
NSLog(#"tideData outside of call back %#", self.tideData);
// this is where I will be setting label text for now, will refactor once I get it working
// rest of file contents........
I have tried a good amount of items related to scoping, clearly just missing the mark. Any ideas? I have searched setting global variables, etc. Been stuck on this for a bit now.
Thanks,
Ryan
The reason you see nil is because you are logging it too soon: when you call
NSLog(#"tideData outside of call back %#", self.tideData);
the get:asJsonAsync: method has not received the results yet.
You can fix this problem by adding a setter for your property, and adding some special handling to it, like this:
-(void)setTideData:(NSDictionary*)dict {
_tideData = dict;
NSLog(#"tideData outside of call back %#", _tideData);
}
This method will be called from the asynchronous code when you do the tideData = ... assignment.
Try setting the object on main thread:
[self performSelectorOnMainThread:#selector(setTideData:) withObject:[NSJSONSerialization JSONObjectWithData:self.rawResults options: 0 error: &error] waitUntilDone:NO];
- (void)setTideData:(NSDictionary*)dict {
self.tideData = dict;
}

iOS Get User Location as NSString

What I want to accomplish in my app is to get the current user location and display it onscreen in a UILabel. I would like to have an NSString of current user's location with a format similar to this: #"City, State/Country". It would be a one-time operation at the start of the app launch.
I have no prior experience with location in iOS and I would like to get some advice on this one - I'm sure it's quite a simple task.
The process is as follows:
Add CoreLocation.framework to your project. See Linking to a Library or a Framework. If you want to use the address book constants that I use below, you might want to add the AddressBook.framework to your project, too.
Start location services. For this purpose, the "significant change" service (less accurate, but lower power consumption) is probably sufficient for city-level accuracy.
When the location manager informs you of the user's location, then perform a reverse geocode of that location.
Stop location services.
Thus, that might look like:
#import <CoreLocation/CoreLocation.h>
#import <AddressBook/AddressBook.h>
#interface ViewController () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self startSignificantChangeUpdates];
}
- (void)startSignificantChangeUpdates
{
if ([CLLocationManager locationServicesEnabled])
{
if (!self.locationManager)
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager startMonitoringSignificantLocationChanges];
}
}
- (void)stopSignificantChangesUpdates
{
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = placemarks[0];
NSDictionary *addressDictionary = [placemark addressDictionary];
NSString *city = addressDictionary[(NSString *)kABPersonAddressCityKey];
NSString *state = addressDictionary[(NSString *)kABPersonAddressStateKey];
NSString *country = placemark.country;
self.label.text = [NSString stringWithFormat:#"%#, %#, %#", city, state, country];
}];
[self stopSignificantChangesUpdates];
}
Note, the location manager's notification of the location is contingent upon the user electing to share that with your app and will happen, even in the best case scenario, asynchronously. Likewise the reverse geocode happens asynchronously.
See Getting User Location from the Location Awareness Programming Guide.
Use -reverseGeocodeLocation:completionHandler: of CLGeocoder.
Try this code snippet, the only trick is that the CLPlacemark (see the Documentation for available info) you get back from the Geocoder has a bunch of info which isn't always consistent, this was one of my tries from an older project, trying to test for location, street name etc... test with your usage case to find a good match:
- (void)getLocationStringForCoordinates:(CLLocationCoordinate2D)coordinates {
if ( CLLocationCoordinate2DIsValid(coordinates) ) {
CLLocation *photoLocation = [[CLLocation alloc] initWithLatitude:coordinates.latitude longitude:coordinates.longitude];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:photoLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *locationPlacemark = [placemarks lastObject];
// Location (popular name, street, area)
NSString *location = locationPlacemark.subLocality ? locationPlacemark.subLocality : (locationPlacemark.name ? locationPlacemark.name : locationPlacemark.thoroughfare);
// sometimes the location can be the same
// as the city name (for small villages), if so
// make sure location is nil to skip it
// else if
// the location name is not being used but is very short 9less then 20 letters, use that instead
if([locationPlacemark.name isEqualToString:locationPlacemark.locality] && [location isEqualToString:locationPlacemark.name])
location = #"";
else if ( ![locationPlacemark.name isEqualToString:location] && locationPlacemark.name.length < 20 )
location = locationPlacemark.name;
// city
NSString *city = locationPlacemark.subAdministrativeArea ? locationPlacemark.subAdministrativeArea : locationPlacemark.locality;
city = city.length > 0 ? [#", " stringByAppendingString:city] : city;
NSString *locationName = [NSString stringWithFormat:#"%#%#", location, city];
}];
}
}
I've found a really nice and simple to follow tutorial on this topic - http://www.appcoda.com/how-to-get-current-location-iphone-user/
Hope it will be helpful to others!
Take a look at the reverseGeocodeLocation:completionHandler: method for CLGeocoder:
http://developer.apple.com/library/ios/#documentation/CoreLocation/Reference/CLGeocoder_class/Reference/Reference.html#//apple_ref/doc/uid/TP40009573
First you will have to use a CLLocationManager to get a CLLocation representing the user's current position.

How to update plist's address to Mapview?

I follow below code, the output can printed to the console, but how to update on the MapView?
- (void)viewDidLoad {
[super viewDidLoad];
/* We have our address */
NSString *oreillyAddress = #"1005 Gravenstein Highway North, Sebastopol, CA 95472, USA";
/* We will later insert the address and the format that we want our output in, into this API's URL */
NSString *geocodingURL = #"http://maps.google.com/maps/geo?q=%#&output=%#";
/* Insert the address and the output format into the URL */
NSString *finalURL = [NSString stringWithFormat:geocodingURL, oreillyAddress, GOOGLE_OUTPUT_FORMAT_CSV];
/* Now escape the URL using appropriate percentage marks */
finalURL = [finalURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
/* Create our URL */
NSURL *urlToCall = [NSURL URLWithString:finalURL];
/* And a request for the connection using the URL */
NSURLRequest *request = [NSURLRequest requestWithURL:urlToCall];
/* We will put all the connection's received data into this instance of the NSMutableData class */
NSMutableData *newMutableData = [[NSMutableData alloc] init];
self.connectionData = newMutableData;
[newMutableData release];
NSURLConnection *newConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
/* Create the connection and start the downloading of geocoding results */
self.myConnection = newConnection;
[newConnection release];
}
- (void) viewDidUnload{
[super viewDidUnload];
[self.myConnection cancel];
self.myConnection = nil;
self.connectionData = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
/* Support all orientations */
return YES;
}
- (void)dealloc {
[myConnection cancel];
[myConnection release];
[connectionData release];
[super dealloc];
}
#end
You must be getting the lat-long information for the location. You will have to create a class that adopts the MKAnnotation protocol and add an instance of it storing the location you get to the MKMapView object using the addAnnotation: method. If the location is within the displayed region of the map, the map view object will call the delegate method mapView:viewForAnnotation: to get the view to display for that annotation. So you will have to become the delegate by adopting the MKMapViewDelegate protocol. Implement the mapView:viewForAnnotation: method to return an MKPinAnnotationView instance or your own subclass' of MKAnnotationView.
If the location is not within the displayed region, then use setRegion:animated: method to move to the location.

Refreshing a MKMapView when the user location is updated or using default values

I'm trying to refresh my map view and load new data from the server when the device acquires the user location.
Here's what I'm doing:
- (void)viewDidLoad {
CGRect bounds = self.view.bounds;
mapView = [[MKMapView alloc] initWithFrame:bounds];
mapView.showsUserLocation=YES;
mapView.delegate=self;
[self.view insertSubview:mapView atIndex:0];
[self refreshMap];
}
- (void)mapView:(MKMapView *)theMapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
//this is to avoid frequent updates, I just need one position and don't need to continuously track the user's location
if (userLocation.location.horizontalAccuracy > self.myUserLocation.location.horizontalAccuracy) {
self.myUserLocation = userLocation;
CLLocationCoordinate2D centerCoord = { userLocation.location.coordinate.latitude, userLocation.location.coordinate.longitude };
[theMapView setCenterCoordinate:centerCoord zoomLevel:10 animated:YES];
[self refreshMap];
}
}
- (void)refreshMap {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[self.mapView removeAnnotations:self.mapView.annotations];
//default position
NSString *lat = #"45.464161";
NSString *lon = #"9.190336";
if (self.myUserLocation != nil) {
lat = [[NSNumber numberWithDouble:myUserLocation.coordinate.latitude] stringValue];
lon = [[NSNumber numberWithDouble:myUserLocation.coordinate.longitude] stringValue];
}
NSString *url = [[NSString alloc] initWithFormat:#"http://myserver/geo_search.json?lat=%#&lon=%#", lat, lon];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
[url release];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
I also have a - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data, to create and add the annotations.
Here's what happens:
sometimes I get the location after a while, so I already loaded data close to the default location.
Then I get the location and it should remove the old annotations and add the new ones, instead I keep seeing the old annotations and the new ones are added anyway (let's say I receive 10 annotations each time, so it means that I have 20 on my map when I should have 10).
What am I doing wrong?
Ok this might be a little long but it worked for me and I really do hope it will help you.
This is from an app that is used to share different traffic status reports between drivers.
I had this problem also, I tried to load annotations from a server, then delete them and reload the annotations array to the map every time the user sends an annotation to the server himself/presses the "refresh" button/every 1.5 minutes - so that he will always have the current set.
So I thought it might have something to do with the time interval that it takes to load the new annotations from the server, or with the array itself, later I realized it might also be connected to the way the entire code was organized and that maybe some things just got in the way/timing of others.
What I did is basically moving the [self.map addAnnotations:AN ARRAY OF ANNOTATIONS] command to the main thread and the whole loading process to the back, I also used a temp array instead of "self.map.annotations" to delete the current annotations, it worked ok afterwards so I just left it like that :), though I'm not a world-class expert (not even close) and I'm sure others might have a more professional and efficient solution, code sample:
//this is in viewDidLoad, it kicks off the whole process
[self performSelectorInBackground:#selector(retrieveAnnotationsDataFromServer) withObject:self];
//this is the method for loading data
-(void)retrieveAnnotationsDataFromServer
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
//code for loading..
NSURL *URL=[NSURL URLWithString:#"http://YOUR SERVER NAME HERE"];
NSString *result=[NSString stringWithContentsOfURL:URL encoding:4 error:nil];
NSLog(#"%#",result);
NSData *data = [NSData dataWithContentsOfURL:URL];
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
[parser setDelegate:self];
[parser parse];
//Inside the parser delegate i take each element of the report and store it in a mutable array so that i could create the annotations later (report title, report description/subtitle, report location longitude and report location latitude)
[pool drain];
NSLog(#"retrieveannotatinsdatafromserver pool drained");
}
//Now, in this case the last thing that will happen before the pool is drained is that the parser`s "didEndDocument" method gonna be called, so this is where I delayed the loading like this:
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(#"parser - document ended, creating annotationsArray");
NSLog(#"this is the size of RA Array:%d",[self.recievedTitles count]);
for (int i=0;i<[self.recievedTitles count];i++)
{
//RC=recieved coordinate
//RA=recieved annotation
CLLocationCoordinate2D RC;
RC.latitude=[[self.recievedLatitude objectAtIndex:i] doubleValue];
RC.longitude=[[self.recievedLongitude objectAtIndex:i] doubleValue];
if([self.recievedTitles objectAtIndex:i]==nil)
continue;
Annotation *RA=[[Annotation alloc]initWithCoordinate:RC andTitle:[self.recievedTitles objectAtIndex:i] andSubTitle:[self.recievedSubTitles objectAtIndex:i]];
//the "self.AnnotationsArray" is an array i use to always hold the most current set retrieved from the server
[self.AnnotationsArray addObject:RA];
[RA autorelease];
NSLog(#"RA %d inserted",i);
}
NSLog(#"Data retrieving ended, loading annotations to map");
[self performSelectorOnMainThread:#selector(addAnnotations) withObject:self waitUntilDone:NO];
}
//this method was only defined so that i could apply it in the main thread instead of in the background like the whole loading process.. I'm sure it can be done better.
-(void)addAnnotations
{
[self.Map addAnnotations:self.AnnotationsArray];
NSLog(#"annotations loaded to Map");
}
//now we have retrieved them from the server for the first time, the reloading and refreshing part comes next, this method is called any time the user press refresh, sends a report to the sever, or automatically every 1.5 minutes:
-(void)refreshMap
{
NSArray *annotationsToDelete=[[NSArray alloc] initWithArray:self.AnnotationsArray];
[self.Map removeAnnotations:annotationsToDelete];
[annotationsToDelete release];
[self performSelectorInBackground:#selector(retrieveAnnotationsDataFromServer) withObject:self];
}
Please do comment on my answer since I will also be very happy to learn a less complicated way of solving this matter.
I think most of these type of problems would have been solved if there was a way to "wait until done" when using background threads, because now what happens is that the code continues to run forward before the whole process of downloading-parsing-creating annotation-loading to map process is actually finished.

Resources