Let's say you want to focus your MapView on the current location, then you write some code in didUpdateLocation which processes the current location coordinates.
But if you don't call requestLocation or startUpdatingLocaion on your CLLocationManager object, the method never gets called. Is that correct?
But wether you call requestLocation or startUpdatingLocation if you look on your MapView the blue dot which shows your location moves (e.g. you simulate movement) but didUpdateLocation won't get called automatically.
I am trying to understand why they made a delegate method when you kind of have to call it yourself.
You have to call the startUpdatingLocation ONCE and the didUpdateLocation delegate method will be called every time when the location changes. This is very different compared to what you say.
Related
What can cause the GPS arrow to appear in the status bar, besides calling startUpdatingLocation or startUpdatingHeading on CLLocationManager?
Can it appear when you do any operation using CLLocationManager or CLLocation objects, such as calculating distance between two CLLocations?
If so, does this represent any power drain, as using the GPS would if you startUpdatingLocation?
If you instantiate CLLocationManager, and then call location on it, the GPS arrow will appear.
Is there a way to figure out programmatically if CoreLocation is displaying that alert?
I'm displaying a welcome screen and want to adapt it's look if the alert shows up.
When you call the instance method of CLLocationManager -startUpdatingLocation, you can schedule a NSTimer with interval of 1 second for example and inside the timer callback call the -authorizationStatus class method of CLLocationManager. If it returns kCLAuthorizationStatusNotDetermined, then the alert is shown and the user should choose either to allow or deny. If he denies then the -locationManager:didFailWithError delegate method is called with error code kCLErrorDenied and you should stop updating location.
How can I use an NSTimer and applicationDidEnterBackground method at background for calling locationManager function?
Why would you need a timer? If you set your delegate to receive the callbacks from location updates, you won't need a timer. If you need active location tracking, you will be taking a huge battery hit if it runs for extended periods of time. You would be better off when you enter background to switch to -monitorForSignificantLocationChanges instead. Register your AppDelegate as as the Location Manager Delegate and just do what you need to do from the call backs.
I have a Map View defined in IB and it is set to show the user location.
In my app, in -viewDidAppear, I query self.mapView.userLocation.location.coordinate and it comes back with insane values such as:
latitude: 4.8194501961644877e-49
longitude: 2.2993313035571993e-59
However, the next time -viewDidAppear is called (after I've simply moved to another tabbed view and then back to this one) the userLocation property holds exactly the correct values for my current location.
It seems that at the time of my initial call, the userLocation property has not been initialised but despite having read Apple's documentation I can't see any caveats where it says that this property is only valid after doing xxx.
Is there something that has to happen before userLocation is valid to use or should I just use CLLocationManager and ask it instead?
Thanks in advance for any help.
Sadly, Thomas' suggestion didn't help. What I have since discovered is:
If showsUserLocation is NO, then userLocation is never set correctly and -MapView:didUpdateUserLocation: is never called, consequently I never ever get a sensible location value.
So, to get the user's location I have to set showsUserLocation to YES, however that then means that after all my annotations have been added to the view (without including the user's location) I then calculate the required span to encompass them all and display them all at the right zoom level. After I do that though, the view jumps sideways as the Map View then automatically displays the user's location as the blue blob! As it was never included in the annotations to work out the zoom level I can't incorporate it into my calculations. Aaargh!
Note that when showsUserLocation is YES, then -MapView:didUpdateUserLocation: is called, but only after I've calculated all the coordinates of my annotations, not before!
I'm assuming it hasn't finished finding the user location - it has to work this out and it may take a while.
Instead of using it in viewDidLoad use THIS delegate method:
- (void)mapView:(MKMapView *)myMapView didUpdateUserLocation:(MKUserLocation *)userLocation;
You will need to set your mapview delegate to self. :)
Same is often true of Core Location. You'll get the last location lingering it its buffer, sometimes, or a super-broad throw-the-dart-at-the-map kind of location...
Best bet is to check the .horizontalAccuracy property of the location object and toss any that are too vague. It's good practice to just chuck the first one too.
for didUpdateUserLocation to be called you have to have...
mapView.showsUserLocation = TRUE;
I was wondering if anyone could point me to (or paste in) some code to deal with turning off Core Location updates to save power.
As far as I understand it, you should stop Core Location updates as soon as you get a reading of desired accuracy. If you don't get a good accuracy reading after a certain time, you should also stop updates (presumably using a timer). Every time you stop updates, you should fire a timer (around 60 seconds) to restart Core Location and get a new reading.
Is there Apple code which does all this? The LocateMe, TaggedLocations and Locations sample code don't seem to do it.
The LocateMe example has the code you need. You just need to create a second Selector to Fire.
LocateMe calls the following in it's setup method...
[self performSelector:#selector(stopUpdatingLocation:) withObject:#"Timed Out" afterDelay:[[setupInfo objectForKey:kSetupInfoKeyTimeout] doubleValue]];
It says that after a certain amount of time (kSetupInfoKeyTimeout), please call the stopUpdatingLocation method the the argument of NSString = "Timed Out".
Inside the stopUpdatingLocation method, the [locationManager stopUpdatingLocation] is called to tell CoreLocation to stop.
So, all you need to do is add another Selector like this...
[self performSelector:#selector(timeToRestartCoreLocation) afterDelay: 60];
inside the stopUpdatingLocation method, which will call the timeToRestartCoreLocation method after 60 seconds. Then inside your timeToRestartCoreLocation method, call [locationManager startUpdatingLocation] to kick off CoreLocation again.