Why is my userLocation.location always nil? - swift

I have mkmapview delegate to handle authorization events, etc., however, my userLocation is real, but my userLocation.location always returns nil in simulator or on device.
Any pointers on why?

Be sure you have added :
NSLocationWhenInUseUsageDescription in your info.plist project file
Register for CLLocationManagerDelegate
mapView.showsUserLocation=YES;
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
}
Hope it will help
Test this behavior on your device is Simpler ( or don't forget to set a location in your simulator configuration )

Related

Gps location icon is not off

In my app, I implemented Cllocation manager to use current user location & it works fine. But when the app enter in background or terminate,the GPS location icon is hide automatically in ipod. When i try same with Iphone, the icon is not hide.
So, i can't find any solution for it. Help me!!
My code is as follow:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if(locationManager == nil)
locationManager =[[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy= kCLLocationAccuracyBest;
self.locationManager.distanceFilter= 5;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
self.userLocation=newLocation;
[self.locationManager startMonitoringSignificantLocationChanges];
}
Map.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[APPDELEGATE.locationManager startUpdatingLocation];
}
- (void)viewWillAppear:(BOOL)animated
{
self.map.delegate = self;
[self.map setShowsUserLocation:YES];
}
if i manually on location service for my app in ipod,when the app is closed, it not shown location icon. But when i try for the same in iphone,it shows location icon.
finally i solved this problem like below.
Instead of
[self.locationManager startMonitoringSignificantLocationChanges];
In appdelegate
i write,
[self.locationManager stopMonitoringSignificantLocationChanges];
I think what you really want is:
[self.locationManager stopUpdatingLocation];
directly afterward, if you want the manager to wake up on a significant location change, then call:
[self.locationManager startMonitoringSignificantLocationChanges];
The opposite applies to go back to continuous updating:
[self.locationManager stopMonitoringSignificantLocationchanges];
[self.locationManager startUpdatingLocation];
Note: When in Significant Location Change mode, the icon in status bar will still show the same as when updating location continuous. This is not an issue for concern as in the conservative mode it is still shutting the location services down when unneeded.
The ipod does not support startMonitoringSignificantLocationChanges. That is why the indicator behaves differently on the two devices.
You should consider that, as you have it implemented, you are using whatever the first event reports for location out of the manager. This can often be stale, cached, old or very likely horribly inaccurate. It is standard practice to use a bit of testing and give a chance for more suitable location info as needed for your purpose.
See my handler on Github for more help as you work with location services.

Should an app start location tracking in order to get ANY last known location from CLLocationManager?

Currently, developing an app that needs to get last location from CLLocationManager (without any regular tracking). It doesn't matter how old, accurate it is. I don't need and want to start tracking - I just need to just grab some last location from a cache and that's it. IMHO, CLLocationManager is a shared component in iOS and if some app uses location tracking then another app should be able to use the most recent location from CLLocationManager.location. It should be sufficient just to alloc/init CLLocationManager and grab its location. However it's not. I have tested on iPhone4 - started google maps, saw my current location, then went to my app, but after [[CLLocationManager alloc] init] location property is nil.
UPDATE: tried [locationManager startUpdatingLocation]; and [locationManager stopUpdatingLocation]; but the result is the same. I guess, the only solution is to start regular tracking?
UPDATE2: Strange but there's no alert with "The app wants to use location services" after alloc/init of CLLocationManager. Here's my code fragment:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
[locationManager stopUpdatingLocation];
NSLog(#"%#", locationManager.location); //prints nil
First you should check if your locationManager has a, let's say, 'static' location pre-saved.
If it does, you're done.
If not, you should startUpdatingLocation and then, in the didUpdateToLocation:fromLocation: callback, stopUpdatingLocation once you get the location.
My experience says that's the best way to get only one location.
UPDATE TO MATCH AUTHOR UPDATES:
You should not stopUpdatingLocation just after startUpdatingLocation. startUpdatingLocation starts a service in background, so you should wait until you get a location, so invoque it in the callback methods.
To make any use of CLLocationManager you need to implement CLLocationManagerDelegate somewhere.
-[CLLocationManager startUpdatingLocation] starts an async process. If you stop it in the same runloop cycle the process never gets started and that is the reason you never see the permission dialog.
It goes something like this:
#interface MyClass : NSObject <CLLocationManagerDelegate> {
CLLocationManager *manager;
CLLocation *lastLocation;
}
#end
#implementation
- (id)init {
self = [super init];
if (self) {
manager = [[CLLocationManager alloc] init];
manager.delegate = self;
[manager startUpdatingLocation];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
{
lastLocation = newLocation;
[manager stopUpdatingLocation];
}
// in your real implementation be sure to handle the error cases as well.
#end

CLLocationManager prompt is displaying alert then disappearing

This is one awful bug. When using CLLocationManger, either with startUpdatingLocation or with ALAsset methods to access metadata for a photo, the system is prompting for location access as expected...but the prompt disappears as soon as it's shown. I cannot find the reason for this and am hoping someone else has had this problem. This does not occur with other alerts (such as showing a UIAlertView).
I can even set the purpose property, and it displays, but again, only for a moment then it just closes itself.
This is a big issue for me as I require permission in order to use photo metadata.
Are you creating the CLLocationManager instance in a method like so:
-(void) viewDidAppear:(BOOL)animated {
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
If so, then as soon as the function exits, the local locationManager variable is being cleaned up. You should save a reference to the locationManager either on an instance or in a static variable:
static CLLocationManager *locationManager;
-(void) viewDidAppear:(BOOL)animated {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
Ugh, now the issue appears to be resolved. And I don't know why or how.

stop location updates from the iphone UI?

Is it possible to start / stop location updates from the UI of the iphone? All I need from the app is to show me my location unless I click "stop" and then "start" again.
I can't seem to be able to do that...I have my location displayed properly, and I also created two IBButtons and created a function for each of them, however, my app crashes when I click on each one of those buttons. I placed those functions under the viewcontroller.m.
I am kind of new to this, so any help would be appreciated. Thanks!
(IBAction)startUpdating: (CLLocation *)location
{
[location startUpdatingLocation];
}
(IBAction)stopUpdating: (CLLocation *)location
{
[location stopUpdatingLocation];
}
start/stopUpdatingLocation are CLLocationManager instance methods, rather than CLLocation instance methods... so create a CLLocationManager instance.
.h
#interface someClass:somesuperclass{
CLLocationManager * locationManager;
BOOL updating;
}
-(IBAction)toggleUpdating:(id)sender;
#end
.m somewhere in the view load/ or init cycle:
-(void)viewDidLoad{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
}
-(void)viewDidUnload{
[locationManager stopUpdatingLocation];
[locationManager release];
[super viewDidUnload];
}
-(IBAction)toggleUpdating:(id)sender
{
if(!updating)
{
[locationManager startUpdatingLocation];
}else{
[locationManager stopUpdatingLocation];
}
updating = !updating;
}
also your action above will never work, because the thing after a colon in an action will be the object that sent the action, a UIButton in your case.

CLLocationManager crashing on release, but why?

This might be one of those silly question where, once a solution is pointed out, makes you feel pretty stupid wondering how you didn't see it but I can't figure out why this part of my app is crashing with EXC_BAD_ACCESS (and no stack trace).
I have a CLLocationManager *locationManager (ivar declared in interface file) that gets created on viewDidLoad if locationServices is enabled:
- (void)viewDidLoad
{
[super viewDidLoad];
if ([CLLocationManager locationServicesEnabled])
[self findUserLocation];
...
}
#pragma mark - Location finder methods
- (void)findUserLocation
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
[locationManager startUpdatingLocation];
}
So the location manager starts updating location and each time and update is found, the delegate method below is called, where I check to see if I should time out or continue looking for my desiredAccuracy:
#pragma mark - CLLocationManager delegates
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if ([newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp] > 8)
[self locationManagerTimeOut];
else if ((newLocation.horizontalAccuracy <= manager.desiredAccuracy) && (newLocation.verticalAccuracy <= manager.desiredAccuracy))
[self locationManagerLockedPosition];
}
If a position is locked, this method is called:
- (void)locationManagerLockedPosition
{
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
[locationManager release], locationManager = nil;
NSLog (#"add results to view");
}
If it times out, this is the method called:
- (void)locationManagerTimeOut
{
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
[locationManager release], locationManager = nil;
NSLog (#"Time out!");
}
Problem is, in either case (time out or locked position), I get the NSLog output in the console and then 2 secs later the app crashes??
Interesting thing is, if I comment out my [locationManager release]... line, everything works fine but WHY? Also if I move the [locationManager release] to my dealloc method, no crashes either!
Am I missing something basic here?
Thanks!
Rog
I had the same issue and there's probably some problem in the depths of CLLocationManager. Fixed by doing:
[locationManager stopUpdatingLocation];
[self performSelector:#selector(discardLocationManager) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO];
and in discardLocationManager do:
- (void) discardLocationManager
{
locationManager.delegate = nil;
[locationManager release];
}
You are release the CLLocationManager instance from within a callback method, which can't be a good idea.
The CLLocationManager calls your callbacks locationManager:didUpdateToLocation:fromLocation etc. If you release the location manager instance, you're basically deallocating the object that just called you. Bad idea. That's why the app crashes.
Instead of releasing the location manager instance, you could autorelease it.
Sargon