didUpdateUserLocation not calling with view reloaded - ios

I'm getting an error in my IOS application. I've searched in the google and here, but the specific solution was not found!
I have a viewController called mapView that I use in two moments in my app, this view contains a MKMapView and the code.
In my mapView.h there is:
#property (strong, nonatomic) IBOutlet MKMapView *mapSpot;
And in my mapView.m there is:
- (void)viewDidLoad {
[super viewDidLoad];
[mapSpot setShowsUserLocation:YES];
}
- (void) mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([userLocation coordinate], 500, 500);
[mapSpot setRegion:region animated:YES];
}
So, in the first moment I load the mapView into other ViewController using:
#property (strong, nonatomic) ViewMap *mapView;
mapView = [[ViewMap alloc] initWithNibName:#"ViewMap" bundle:nil];
[self.view addSubview:[mapView view]];
I unload that ViewController and in another ViewController in other moment I load the MapView again, but in this moment the method: - (void) mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation not is called.
I verify if the first ViewController was unloaded and that was.
When I load the second ViewController there is a new instace of MapView, but not call the delegate method.
Anyone know something about that?
Thanks
==================================================================================
EDIT AND SOLVED:

the problem is in the way you are adding the view, in this line
[self.view addSubview:[mapView view]];
if you only add the view the controller code is not executed, instead of that you has to present the mapView, for example:
[self presentViewController:mapView animated:YES completion:nil];

The problem above, maybe happen because I'm using simulator to test app, and how the simulator not change the position map not get didUpdateUserLocation:
That's the unique explanation that I could have after the review the code, organize the classes read documentation and get error again.
Now, I'm using CLLocationManager to get position, after getting first time the position I stop it.
In the future I'll implement a system that track the user path, so using CLLocationManager is inevitable.
The mapView.m code after changes:
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation *loc = [locations lastObject];
// store the location to use in any moment, it needs to be checked because the first time when get the coordinate not pass infos to load places according the current position
if (!location.latitude) {
location = [loc coordinate];
// set center the map at the current position
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(location, 500, 500);
[mapSpotView setRegion:region animated:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:#"loadPlaces" object:nil];
[locationManager stopUpdatingLocation];
}
}
if someone has a better solution, please, post here!
That's it!

Related

Getting coordinates CLLocationManager IOS

I'm trying to getting my current location exact according to my coordinates. I've implemented CLLocationManager in my viewController called myLocation.
My problem is, I'm getting not getting my co-ordinates for the first time, but when I again approach I got the coordinates. I'm unable to understand this problem that why this not appear for the first time.
I also tried to give a NSTimer to stoplocation but but still unable to get the result for the first time, every first time I getting a (null) value, and then getting the co-ordinates.
My Code:
#import <UIKit/UIKit.h>
#import <Corelocation/CoreLocation.h>
#interface myLocation : UITableViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#interface myLocation () {
CLLocationManager* _locationManager;
NSString * _lat;
NSString * _lng;
}
#end
#implementation myLocation
- (void)viewDidLoad
{
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[_locationManager requestWhenInUseAuthorization];
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
[_locationManager stopUpdatingLocation];
_lat =[NSString stringWithFormat:#"%f",location.coordinate.latitude];
_lng =[NSString stringWithFormat:#"%f",location.coordinate.longitude];
}
- (void)viewWillAppear:(BOOL) animated
{
NSLOG(#"%#",_lat);
NSLOG(#"%#",_lng);
}
Your coordinates aren't appearing yet when you attempt to print them in viewWillAppear: because the CLLocationManager hasn't had enough time to retrieve the first location yet. Wait until didUpdateLocations: is first called before attempting to utilize the device coordinates because didUpdateLocations: is where you'll be receiving those coordinates. I recommend deleting your attempt to print the coordinates code from your viewWillAppear and simply print them in didUpdateLocations: instead.
In the comments, the OP stated he wants to "refresh" the location during viewWillAppear. I suggest stopping the updates when the view disappears and restarting the updates as soon as the view reappears:
- (void)viewWillAppear:(BOOL) animated
{
[_locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL) animated
{
[_locationManager stopUpdatingLocation];
}
It takes some time for location services to start up and call your delegate method - This almost certainly won't happen before viewWillAppear is called if you are only starting location services in viewDidLoad. Also, the first time your app executes it has to wait for the user to grant permission.
You can examine the location property of your CLLocationManager to get the most recent location. If it is nil then no location has been determined (yet).

MKMapView tiles not loaded with zoom

I've got an issue. I'm using a MKMapView for displaying some annotations. I initialize a map view with default zoom. And it displays some map.
but when i try zooming, tiles not loaded, and map becomes empty. Like this.
I create my Map View via interface builder.
#property (nonatomic, weak) IBOutlet MKMapView* mapView;
What am I doing wrong? Is there any mandatory methods for implementation, that affect on this functional? And yes, there is an internet connection on my device.
Generally this can happens due to internet connection. If you have slow internet connection than it takes time to load map tiles.
About methods i recommended to override below method.
Override MKMapView delegate method -
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
Will call every time you zoom in/out and load map tiles.
PS - provide MKMapViewDelegate to your view controller.
I had the same loading problem till I got the problem working by googling!
Note: Effective ios 8 & later, we need to add a value NSLocationWhenInUseUsageDescription in Info.plist file with our own value as description. This is because showsUserLocation property of **MKMapView** doesn't work straight away. More info here !!!!
//This should be declared in .h file
#property(nonatomic, strong) CLLocationManager *locationManager;
- (void)viewDidLoad {
self.mapView.showsUserLocation = YES;
self.mapView.delegate = self;
self.locationManager.delegate = self;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER) {
[self.locationManager requestWhenInUseAuthorization];
}
#endif
[self.locationManager startUpdatingLocation];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
self.mapView.showsUserLocation = YES;
}
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region;
region.center = self.locationView.userLocation.coordinate;
MKCoordinateSpan span;
span.latitudeDelta = 0.015; ->Adjust this value to zoom as per your requirement
span.longitudeDelta = 0.015;
region.span = span;
[self.mapView setRegion:region animated:YES];
}
I firmly believe this will yield the expected result without fail, i.e. MKMapView zoom to the current user location.

iOS: Get current location coordinates without using MKMapView

I'd like to be able to get my current user's location without actually having a map view on my view controller.
At the moment I do have a map view and get the user location by calling one of the delegate methods....
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
userlatitude = userLocation.location.coordinate.latitude;
userlongitude = userLocation.location.coordinate.longitude;
}
CLLocationManager is the class that is responsible for keeping user's location values. CLLocationManagerDelegate is another class that gets real time location data from iDevice's GPS and notifies CLLocationManager instance about the change in location and various other events, via it's delegate methods. It would be very helpful if you would read the related documentation.
You must implement CLLocationManagerDelegate protocol inside your class.
You must also have CLLocationManager instance within your class that should monitor the location.
In your project, you must also add Core Location framework in Link Binaries section.
The simplest way would be:
Your .h file:
#interface MyViewController : UIViewController<CLLocationManagerDelegate>
{
CLLocation * currentLocation;
CLLocationManager * locationManager;
}
#end
Your .m file:
- (void) viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
//remember to stop before you are done, either here or in view disappearance.
- (void) dealloc
{
[locationManager stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
currentLocation = (CLLocation *)[locations lastObject];
}
Easily, use CCLocationManager instead of the MKMapKit::userLocaiton method.
Take a look at the "LocateMe" sample project on developer.apple.com.

MKMapView sometimes zoomz to user location sometimes zooms to middle of nowhere

I am using am mapview and sometimes my map will zoom onto my users location when I open it but sometimes it will zoom to the middle of an ocean. I don't know what is causing this, this is the code I am using for zooming. I don't want the map to track the user but just zoom to their location once they open the map
-(void) viewDidAppear:(BOOL)animated{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.coordinate, 600.0f, 600.0f);
[self.mapView setRegion:region animated:YES];
}
-(void) viewDidLoad{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
}
I encountered this issue before. It seems that mapView is slow to load and detect user location sometimes, resulting in your code in viewDidAppear being executed before the map view can check user's location. Thus, the spot in the ocean.
It will be better to use mapView's delegate to display user location when it's ready:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if(isShowUserLocation)
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 600.0, 600.0);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
isShowUserLocation = NO;
}
}
Set isShowUserLocation = YES in viewDidLoad. This ensures the user location is shown once on entry and also selectively when you need it.
Edit 1:
#implementation MapViewController
{
BOOL isShowUserLocation;
}
-(void) viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
isShowUserLocation = YES;
}
Edit 2:
Alternatively, use CLLocationManager - see this post. It allows you stop the updating. Do include CoreLocation.framework. You may need to handle some nitty-gritty issues when interacting CLLocationManager with MapView though.
When you pass 0's for lat and long, you will git a spot in the middle of the ocean south of Ghana in Africa.

call CLLocationManager and its delegates from a model

I'm trying to put everything location related inside a model. When I call this my MainViewController, the simulator doesn't ask me for my location, and nothing happens.
When I use the same code from my model, but put it directly in ViewDidLoad in my ViewController, everything works. I'm having a hard time understanding why.
Here is my model:
#implementation Location
{
CLLocationManager *_locationManager;
CLLocation *_location;
}
- (void)startLocationManager
{
NSLog(#"In startLocationManager");
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
_locationManager.delegate = self;
[_locationManager startUpdatingLocation];
}
#pragma mark - LocationManager Delegates
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"In didUpdateLocations");
if (locations) {
_location = [locations lastObject];
NSLog(#"%#", _location);
}
}
#end
I call this in my MainViewController like this:
- (void)viewDidLoad
{
[super viewDidLoad];
Location *location = [[Location alloc] init];
[location startLocationManager];
}
Why does the code work like a charm directly in the viewController, but not through my model?
I figured it out.
I needed to make location a property of your view controller instead of a local variable in the viewDidLoad. Otherwise it is created and deallocated within that method. I need it to live through the lifecycle of my view controller.

Resources