How to show search address on google map.? - ios

I am working on goole map and i add the following for search bar on google map and get the coordinates of particular search address. Now i want to show it on map also after selection on place. Please look at my code.
-(void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithPlace:(GMSPlace *)place {
// Do something with the selected place.
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
NSLog(#"lat and log%f", place.coordinate.latitude);
NSLog(#"lang %f", place.coordinate.longitude);
CLLocationCoordinate2D *coordinates = CLLocationCoordinate2DMake(place.coordinate.latitude, place.coordinate.longitude);
GMSCameraUpdate *updatedCamera = [GMSCameraUpdate setTarget:coordinates zoom:10];
[_mapView animateWithCameraUpdate:updatedCamera];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewController:(GMSAutocompleteViewController *)viewController
didFailAutocompleteWithError:(NSError *)error {
// TODO: handle the error.
NSLog(#"error: %ld", (long)[error code]);
[self dismissViewControllerAnimated:YES completion:nil];
}
// User canceled the operation.
- (void)wasCancelled:(GMSAutocompleteViewController *)viewController {
NSLog(#"Autocomplete was cancelled.");
[self dismissViewControllerAnimated:YES completion:nil];
}
How will i update lat and long on map?

CLLocationCoordinate2D *coordinates = CLLocationCoordinate2DMake(place.coordinate.latitude,place.coordinate.longitude);
GMSCameraUpdate *updatedCamera = [GMSCameraUpdate setTarget:coordinates zoom:10];
[yourmapViewName animateWithCameraUpdate:cameraUpdate];
Update Answer
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithPlace:(GMSPlace *)place {
// Do something with the selected place.
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
NSLog(#"lat and log%f", place.coordinate.latitude);
NSLog(#"lang %f", place.coordinate.longitude);
CLLocationCoordinate2D coordinates = CLLocationCoordinate2DMake(place.coordinate.latitude,place.coordinate.longitude);
GMSCameraUpdate *updatedCamera = [GMSCameraUpdate setTarget:coordinates zoom:10];
[yourmapViewName animateWithCameraUpdate:cameraUpdate];
[self dismissViewControllerAnimated:YES completion:nil];
}

Related

Google place picker interrupts the background location updates in iPhone

I'm developing a location-based mobile application. My app updates the server with user's current location even when the app is killed/terminated. My app was working fine before integrating google place picker API. After installing google place picker API for ios, my app updates the location for about 5 to 10 minutes only and then it stops updating location.
//My code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize Location Manager
sLocationManager;
//the system automatically relaunches the application into the background if a new event arrives.
// The options dictionary passed to the application:didFinishLaunchingWithOptions: method of your application delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your application was launched because of a location event
if (launchOptions[UIApplicationLaunchOptionsLocationKey]) {
NSLog(#"---UIApplicationLaunchOptionsLocationKey");
sLocationManager.locationUpdatedInBackground = ^(NSArray<CLLocation *> *locations) {
NSLog(#"---setLocationUpdatedInBackground");
[sLocationModule saveNewLocations];
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:300];
notification.alertBody = #"Your location was changed. Please run application for tracking your geoposition with best accuracy.";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
[sLocationManager startMonitoringSignificantLocationChanges];
};
}else {
sLocationManager.locationUpdatedInForeground = ^(NSArray<CLLocation *> *locations) {
NSLog(#"---setLocationUpdatedInForeground");
[sLocationModule saveNewLocations];
};
sLocationManager.locationUpdatedInBackground = ^(NSArray<CLLocation *> *locations) {
NSLog(#"---setLocationUpdatedInBackground");
[sLocationModule saveNewLocations];
[sLocationManager startDeferredLocationUpdates];
};
// Notifications
[application cancelAllLocalNotifications];
}
return YES;
//location manager
#pragma mark - CLLocationManager Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)aLocations {
NSString *infoMessage = [NSString stringWithFormat:#"%#", aLocations];
NSLog(#"%#", infoMessage);
locations = [#[] mutableCopy];
NSLog(#"locations=%#",locations);
[aLocations enumerateObjectsUsingBlock:^(CLLocation * _Nonnull location, NSUInteger idx, BOOL * _Nonnull stop) {
// Check for location errors (speed -1.00 mps / course -1.00)
// if (location.speed >= 0 &&
// location.course >= 0) {
if (locations.count > 0) {
if ([location.timestamp timeIntervalSinceDate:[locations lastObject].timestamp] > dLocationManagerDistanceFilter ||
[location distanceFromLocation:[locations lastObject]] > dLocationUpdatesUntilTimeout) {
[locations addObject:location];
NSLog(#"location.timestamp>dLocationManagerDistanceFilter**** locations=%#",locations);
}
} else
[locations addObject:location];
NSLog(#"else***locations=%#",locations);
//save location in userdefaults
NSString *latitudeValue = [NSString stringWithFormat:#"%f", location.coordinate.latitude];
NSString *longitudeValue = [NSString stringWithFormat:#"%f",location.coordinate.longitude];
NSLog(#"new location is recieved Lat : %# Long : %#",latitudeValue,longitudeValue);
[User setUserLat:latitudeValue];
[User setUserLon:longitudeValue];
// }
}];
if ([self isInBackground]) {
NSLog(#"app is in background***");
if (self.locationUpdatedInBackground) {
backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];
}];
self.locationUpdatedInBackground(locations);
[delegate locationManagerDidUpdateLocationInBackground];
[[NSNotificationCenter defaultCenter] postNotificationName:nLocationManagerDidUpdateLocationInBackgroundNotification
object:nil
userInfo:nil];
[self endBackgroundTask];
}
} else {
if (self.locationUpdatedInForeground) {
if([[NSUserDefaults standardUserDefaults]objectForKey:#"userIdKey"]){
self.locationUpdatedInForeground(locations);
[delegate locationManagerDidUpdateLocationInForeground];
[[NSNotificationCenter defaultCenter] postNotificationName:nLocationManagerDidUpdateLocationInForegroundNotification
object:nil
userInfo:nil];
}
}
}
}
code for adding place picker
#pragma mark - Place picker delegate methods
- (IBAction)pickPlace:(id)sender {
//dismiss the keyboard
[tfLocation resignFirstResponder];
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude);
CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001);
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(center.latitude - 0.001, center.longitude - 0.001);
GMSCoordinateBounds *viewport = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast
coordinate:southWest];
GMSPlacePickerConfig *config = [[GMSPlacePickerConfig alloc] initWithViewport:viewport];
_placePicker = [[GMSPlacePicker alloc] initWithConfig:config];
[_placePicker pickPlaceWithCallback:^(GMSPlace *place, NSError *error) {
if (error != nil) {
NSLog(#"Pick Place error %#", [error localizedDescription]);
return;
}
if (place != nil) {
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
// NSString *latitudeValue = [NSString stringWithFormat:#"%f", locationManager.location.coordinate.latitude];
// NSString *longitudeValue = [NSString stringWithFormat:#"%f",locationManager.location.coordinate.longitude];
tfLocation.text=place.formattedAddress;
locationPoint=[NSString stringWithFormat:#"%f,%f", place.coordinate.latitude,place.coordinate.longitude];
} else {
NSLog(#"No place selected");
}
}];
}
// Add a UIButton in Interface Builder, and connect the action to this function.
- (IBAction)getCurrentPlace:(UIButton *)sender {
[_placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *placeLikelihoodList, NSError *error){
if (error != nil) {
NSLog(#"Pick Place error %#", [error localizedDescription]);
return;
}
self.nameLabel.text = #"No current place";
self.addressLabel.text = #"";
if (placeLikelihoodList != nil) {
GMSPlace *place = [[[placeLikelihoodList likelihoods] firstObject] place];
if (place != nil) {
self.nameLabel.text = place.name;
self.addressLabel.text = [[place.formattedAddress componentsSeparatedByString:#", "]
componentsJoinedByString:#"\n"];
}
}
}];
}
// Present the autocomplete view controller when the button is pressed.
- (IBAction)onLaunchClicked:(id)sender {
GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
// Handle the user's selection.
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithPlace:(GMSPlace *)place {
[self dismissViewControllerAnimated:YES completion:nil];
// Do something with the selected place.
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
}
- (void)viewController:(GMSAutocompleteViewController *)viewController
didFailAutocompleteWithError:(NSError *)error {
[self dismissViewControllerAnimated:YES completion:nil];
// TODO: handle the error.
NSLog(#"Error: %#", [error description]);
}
// User canceled the operation.
- (void)wasCancelled:(GMSAutocompleteViewController *)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
// Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)didUpdateAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
Can anyone tell, what am I doing wrong here? What is the best to use place picker without affecting background location updates or is there any other way to pick place/location just like google place picker in ios?
Please help me out or tell me the other solution.
thank you!

How to clear text inside VENToken?

I have used VENTokenField github library for recipients email. Now the user enter the email and its separated by commas(,). Everything works fine. My question is how to clear the text when user press the submit button.
1) http://imgur.com/a/ObbaB
2) http://imgur.com/a/DCusg
#property (strong, nonatomic) NSMutableArray *inviteFriendNames;
self.inviteFriendNames = [[NSMutableArray alloc]init];
#pragma mark - VENTokenFieldDataSource
- (NSString *)tokenField:(VENTokenField *)tokenField titleForTokenAtIndex:(NSUInteger)index
{
if (self.inviteFriendNames.count > index) {
return self.inviteFriendNames[index];
}
return #"";
}
- (NSUInteger)numberOfTokensInTokenField:(VENTokenField *)tokenField
{
return self.inviteFriendNames.count;
}
#pragma mark - VENTokenFieldDelegate
- (void)tokenField:(VENTokenField *)tokenField didEnterText:(NSString *)text
{
if (![self.inviteFriendNames containsObject:text]) {
self.inviteFriendNames = (NSMutableArray*)[self.inviteFriendNames arrayByAddingObject:text];
[self chosenContactsHasChanged];
}
return;
}
- (void)tokenField:(VENTokenField *)tokenField didDeleteTokenAtIndex:(NSUInteger)index
{
if (self.inviteFriendNames.count > index) {
NSMutableArray *mutable = [self.inviteFriendNames mutableCopy];
[mutable removeObjectAtIndex:index];
self.inviteFriendNames = mutable;
[self chosenContactsHasChanged];
}
self.tokenField.placeholderText = NSLocalizedString(#"Email", nil);
[self chosenContactsHasChanged];
}
- (void)tokenField:(VENTokenField *)tokenField didChangeText:(NSString *)text
{
if ([text hasSuffix:#" "]) {
// Trim off the comma
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#" "]];
[self tokenField:tokenField didEnterText:text];
} else {
return;
}
}
- (void)updateContactTokenFieldHeightConstraint
{
CGFloat heightOfTokens = self.tokenField.tokenScrollViewHeight + tokenFieldHeightPadding;
CGFloat newHeight = MAX(tokenFieldMinHeight, heightOfTokens);
self.tokenFieldHeight.constant = newHeight;
[self layoutIfNeeded];
}
- (void)chosenContactsHasChanged
{
[self.tokenField reloadData];
[self updateContactTokenFieldHeightConstraint];
}
pragma mark - UIButton Action
-(IBAction)inviteButtonAction:(id)sender{
[self endEditing:YES];
if (self.inviteFriendNames.count == 0) {
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:#"Please enter the mail id." completion:nil];
}else{
NSString *senderName = [NSString stringWithFormat:#"%#.%#",[APPDELEGATE.defaults valueForKey:#"firstName"],[APPDELEGATE.defaults valueForKey:#"lastName"]];
NSDictionary *sendData = #{#"name":senderName,#"emails":inviteFriendNames};
[self.inviteVC sendInviationAPI:INVITE_FRIENDS withParameter:sendData];
}
}
pragma mark - To invitation
-(void)sendInviationAPI:(NSString *)url withParameter:(NSDictionary *)parameters{
// To Check Network Available or Unavailable
if (![PCCommonUtility checkForNetwork]) {
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:[LocalizedStrings warning] description:[LocalizedStrings networkFailure] completion:nil];
}else{
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
// To Check Access token is null or empty
if ([APPDELEGATE.defaults valueForKey:CURRENT_TOKEN] && ![[APPDELEGATE.defaults valueForKey:CURRENT_TOKEN]isKindOfClass:[NSNull class]]) {
[PCAPIUtility getResponseFromAPI:url withParameters:parameters withSuccess:^(NSMutableArray *responseData, NSString *success) {
DLog(#"InviteSuccess:%#",responseData);
NSString *status = [NSString stringWithFormat:#"%#",[responseData valueForKey:#"status"]];
NSString *message = [NSString stringWithFormat:#"%#",[responseData valueForKey:#"message"]]
if ([status isEqualToString:#"1"]) {
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:message completion:^(BOOL confirm) {
if (!confirm) {
[self.inviteView.inviteFriendNames removeAllObjects];
[self.inviteView.tokenField reloadData];
}
}];
}else{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:message completion:nil];
}
} orFailure:^(NSError *error) {
DLog(#"InviteFailure:%#",error.description);
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:[LocalizedStrings networkFailure] completion:nil];
}];
}else{
NSLog(#"Access Token is Empty");
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
}
}
In ViewController class,
.h
#protocol DelegateMethod <NSObject>
-(void)removeArray;
#end
#interface ViewController : UIViewController
#property (nonatomic, strong) id <DelegateMethod> delegate;
#end
.m
-(void)sendInviationAPI:(NSString *)url withParameter:(NSDictionary *)parameters{
// To Check Network Available or Unavailable
if (![PCCommonUtility checkForNetwork]) {
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:[LocalizedStrings warning] description:[LocalizedStrings networkFailure] completion:nil];
}else{
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
// To Check Access token is null or empty
if ([APPDELEGATE.defaults valueForKey:CURRENT_TOKEN] && ![[APPDELEGATE.defaults valueForKey:CURRENT_TOKEN]isKindOfClass:[NSNull class]]) {
[PCAPIUtility getResponseFromAPI:url withParameters:parameters withSuccess:^(NSMutableArray *responseData, NSString *success) {
DLog(#"InviteSuccess:%#",responseData);
NSString *status = [NSString stringWithFormat:#"%#",[responseData valueForKey:#"status"]];
NSString *message = [NSString stringWithFormat:#"%#",[responseData valueForKey:#"message"]]
if ([status isEqualToString:#"1"]) {
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:message completion:^(BOOL confirm) {
if (!confirm) {
[self.delegate removeArray];
}
}];
}else{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:message completion:nil];
}
} orFailure:^(NSError *error) {
DLog(#"InviteFailure:%#",error.description);
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:[LocalizedStrings networkFailure] completion:nil];
}];
}else{
NSLog(#"Access Token is Empty");
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
}
}
In View class
Invite Button Action
-(IBAction)inviteButtonAction:(id)sender{
[self endEditing:YES];
if (self.inviteFriendNames.count == 0) {
[[PCAlertUtility sharedInstance]showOkAlertWithTitle:nil description:#"Please enter the mail id." completion:nil];
}else{
NSString *senderName = [NSString stringWithFormat:#"%#.%#",[APPDELEGATE.defaults valueForKey:#"firstName"],[APPDELEGATE.defaults valueForKey:#"lastName"]];
NSDictionary *sendData = #{#"name":senderName,#"emails":inviteFriendNames};
[self.inviteVC setDelegate:self];
[self.inviteVC sendInviationAPI:INVITE_FRIENDS withParameter:sendData];
}
}
-(void)removeArray {
[self.inviteFriendNames removeAllObjects];
[self.tokenField reloadData];
}

Calling API for GoogleMap objective c

Can anyone guide me how we can use place auto complete in GoogleMap after all the steps completed for installing pod for GoogleMaps into the project?? I have no idea about this please somebody help me!!!
I hope u have integrated google pods successfully
Import google map class
#import GoogleMaps;
Add delegate
<GMSAutocompleteViewControllerDelegate>
I have button in my screen to go for autocomplete screen.
On button IBAction write this code
GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
and implement GMSAutocompleteViewControllerDelegate
- (void)viewController:(GMSAutocompleteViewController *)viewControllerdidAutocompleteWithPlace:(GMSPlace *)place {
[self dismissViewControllerAnimated:YES completion:nil];
// Do something with the selected place.
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
}
- (void)viewController:(GMSAutocompleteViewController *)viewControllerdidFailAutocompleteWithError:(NSError *)error {
[self dismissViewControllerAnimated:YES completion:nil];
// TODO: handle the error.
NSLog(#"Error: %#", [error description]);
}
// User canceled the operation.
- (void)wasCancelled:(GMSAutocompleteViewController *)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
// Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictions:(GMSAutocompleteViewController*)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)didUpdateAutocompletePredictions:(GMSAutocompleteViewController*)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

Restrict the Google AutoComplete API to show only nearby locations

For location finding Google AutoComplete works good but its returning the search results all over the world. I want to restrict the search results either with in the 1000 meter radius or in a city. I followed this google link to integrate the autocomplete search. Only this below code used in project
-(void)autoComplete
{
GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
// Handle the user's selection.
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithPlace:(GMSPlace *)place {
[self dismissViewControllerAnimated:YES completion:nil];
// Do something with the selected place.
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
}
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithError:(NSError *)error {
[self dismissViewControllerAnimated:YES completion:nil];
// TODO: handle the error.
NSLog(#"Error: %#", [error description]);
}
// User canceled the operation.
- (void)wasCancelled:(GMSAutocompleteViewController *)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
You cannot 100% restrict it, But you can give more priority to your city by specifying its northeast and southwest corners, Here is the code
GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(northEastLati, northEastLongi);
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(southWestLati, southWestLongi);
acController.autocompleteBounds = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast
coordinate:southWest];
[self presentViewController:acController animated:YES completion:nil];
Now you will get 99% of result will be belongs to your city. Hope it will help you.
Adding Swift Version.
If your autocompleteController is being presented, refresh it by calling
updateCoordinateBoundsOnAutoCompleteController()
/* Returns Bounds */
func getCoordinateBounds(latitude:CLLocationDegrees ,
longitude:CLLocationDegrees,
distance:Double = 0.001)->GMSCoordinateBounds{
let center = CLLocationCoordinate2D(latitude: latitude,
longitude: longitude)
let northEast = CLLocationCoordinate2D(latitude: center.latitude + distance, longitude: center.longitude + distance)
let southWest = CLLocationCoordinate2D(latitude: center.latitude - distance, longitude: center.longitude - distance)
return GMSCoordinateBounds(coordinate: northEast,
coordinate: southWest)
}
/* Refreshes AutoCompleteController */
func updateCoordinateBoundsOnAutoCompleteController(){
autocompleteController.viewWillAppear(true)
autocompleteController.viewDidAppear(true)
}

[iOS][Background][CLLocationManager]Bad map accuracy

I am working on an application which aims to display on a map the position of the iPhone during an activity (adding annotations and drawing line between them).
To do this, I use a Location Manager which get new positions and notify the MapDisplayViewController. When using with the simulator I got good results as you can see here http://www.youtube.com/watch?v=ESLIYSU_Mqw but with an iPhone I got weird result such 200 meters wrong.
I also use a MKMapView to display the device position. with these settings (next code block) I got that http://grab.by/mgUU.
If I show the user location I got different results, it is normal ?
- (void)setupMap {
self.mapView.delegate = self;
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
[self.mapView setUserInteractionEnabled:NO];
[self.mapView setShowsUserLocation:NO];
[self.mapView setZoomEnabled:NO];
[self.waitingView start];
}
Here screenshots with a real device:
background: http://grab.by/mgN2
no background: http://grab.by/mgNc
edit: the difference come froms I used for these 2 cases, 2 different ways of getting current location of the device are used:
the handle from the mapView when the app is active
the handle from the Location Manager when the app is in background
Does it a good idea to mix both locations system ?
I also test this solution CLLocationManager and accuracy issues - any experiences? but I got the same result.
Thanks ;)
Setup of Location Manager:
- (void)setup {
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.isUpdatingLocation = NO;
}
Notification: when adding location in background:
- (void)doUpdateWithLocation:(CLLocation *)location {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginBackgroundUpdateTask];
NSLog(#"%s do update in background %#", __PRETTY_FUNCTION__, location);
if (self.userLocationFound == NO && self.isUpdatingLocation == YES) {
self.startCoordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
self.userLocationFound = YES;
}
else if (self.isUpdatingLocation) {
static int distance;
ABGPSPosition *position = [[ABGPSPosition alloc] init];
position.startPoint = MKMapPointForCoordinate(self.startCoordinate);
position.endPoint = MKMapPointForCoordinate(location.coordinate);
//INFO: Get the distance between this new point and the previous point.
CLLocationDistance metersApart = MKMetersBetweenMapPoints(position.startPoint, position.endPoint);
if (metersApart > MINIMUM_DELTA_METERS) {
MKMapPoint points[2] = {position.startPoint, position.endPoint};
distance += metersApart;
NSLog(#"%s - %d", __PRETTY_FUNCTION__, distance);
NSInteger count = [self.measurementArray count];
[self willChange:NSKeyValueChangeInsertion
valuesAtIndexes:[NSIndexSet indexSetWithIndex:count] forKey: #"measurementArray"];
[self.measurementArray insertObject:location atIndex:count];
[self didChange:NSKeyValueChangeInsertion
valuesAtIndexes:[NSIndexSet indexSetWithIndex:count] forKey: #"measurementArray"];
self.startCoordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
}
}
[self endBackgroundUpdateTask];
});
}
MapDisplayViewController get the new location:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:keyPathMeasurementArray]) {
if ([change[NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeInsertion) {
NSIndexSet *insertedIndexSet = change[NSKeyValueChangeIndexesKey];
[insertedIndexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
CLLocation *location = self.locationManager.measurementArray[idx];
MKUserLocation *userLocation = [[MKUserLocation alloc] init];
[userLocation setCoordinate:location.coordinate];
NSLog(#"%s - didUpdateUserLocation", __PRETTY_FUNCTION__);
[self.locationBackgroundList addObject:userLocation];
NSLog(#"%s | %#", __PRETTY_FUNCTION__, self.locationBackgroundList);
}];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
MapDisplayViewController adding Annotation the new map view:
- (void)handleAddLocations {
NSLog(#"%s | %#", __PRETTY_FUNCTION__, self.locationBackgroundList);
if ([self.locationBackgroundList count] > 0) {
for (MKUserLocation *backgroundUserLocation in self.locationBackgroundList) {
{
LocAnnotation* annotation = [[LocAnnotation alloc] initWithCoordinate:backgroundUserLocation.coordinate];
NSLog(#"%s %#", __PRETTY_FUNCTION__, [backgroundUserLocation description]);
[self.mapView addAnnotation:annotation];
}
[self mapView:self.mapView didUpdateUserLocation:backgroundUserLocation];
}
NSString *message = [NSString stringWithFormat:#"%s | Annotation number: %d", __PRETTY_FUNCTION__, [self.locationBackgroundList count]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Debug" message:message delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[alert show];
[self.locationBackgroundList removeAllObjects];
self.locationBackgroundList = [[NSMutableArray alloc] init];
}
}
Fixed you have to use only one way to locate your device with the CLLocationManager or the MapView. ;)

Resources