I am facing a strange problem. I am using
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations to get device location. It is working fine on simulator (iOS 6 and iOS 7) and iPhone 4S running iOS 6.1.3. It is also working fine when I connect iPhone 4 running iOS 7 to system and install the app but as soon as I unplug the device and re-run the app, this method doesn't get called and I don't get the location. How can I overcome this issue?
How did you setup you location Manager?
Do you have in your interface:
#interface ViewController : UIViewController <CLLocationManagerDelegate> {
#property (strong, nonatomic) CLLocationManager *locationManager;
}
Then in implementation in viewDidLoad:
// setup location manager
if ([CLLocationManager locationServicesEnabled]) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.delegate = self;
[_locationManager startUpdatingLocation];
}
And you need to implement the delegate:
locationManager:didUpdateLocations:
Be careful: In IOS 7
locationManager:didUpdateToLocation:fromLocation
is deprecated.
Apple link to CLLocationManagerDelegate
Related
I have been trying to move my iOS7 app with MKMapview to support iOS8. However I couldn't get the new request for users to share their locations to work properly. I create my MKMapView on a storyboard and the delegate is set and works perfectly on iOS7. Here is what I've added to support iOS8 Location sharing:
myMapView.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface myMapView : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocationManager *locationManager;
myMapView.m
//Code omitted
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
//Code omitted
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if(IS_OS_8_OR_LATER) {
//[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
}
[self.mapView setShowsUserLocation:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = self.locationManager.location.coordinate.latitude;
region.center.longitude = self.locationManager.location.coordinate.longitude;
region.span.latitudeDelta = 0.0187f;
region.span.longitudeDelta = 0.0137f;
[self.mapView setRegion:region animated:YES];
_initialPosition = NO;
}
Also I have set NSLocationAlwaysUsageDescription key and its value in my InfoPlist, which shows the correct message when prompting the user to share their location.
Unfortunately the delegate function -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations never gets called. Although each time the viewController gets loaded the [self.locationManager startUpdatingLocation] is called, but the delegate does not seem to respond to it. Is there a problem of how I set the delegate or is there something else I am missing here?
UPDATE: It seems also that my gpx file is not being called on launch. I have cleared and reloaded my location file, even changed to a default location, but no location is found: Domain=kCLErrorDomain Code=0
UPDATE 2: Here is a SS from the settings that I have actually succeeded with the user request, but fail to get/update location no matter how much I refresh.
(source: barisaltop.com)
Thanks!
I had the same problem a few days ago. The solution was adding the string keys NSLocationAlwaysUsageDescription (for [CLLocationManager requestAlwaysAuthorization]) or NSLocationWhenInUseUsageDescription (for [CLLocationManager requestWhenInUseAuthorization]) to your Supporting Files/Info.plist
You can also edit the source code of the Info.Plist with Right click > open as > Source code and add these lines:
<!-- for requestAlwaysAuthorization -->
<key>NSLocationAlwaysUsageDescription</key>
<string>Explain for what are you using the user location</string>
<!-- for requestWhenInUseAuthorization -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Explain for what are you using the user location</string>
Hope this helps.
Finally I have succeeded to run my gpx file on the simulator. It seems that after installing Xcode 6 the first time, there might be a bug causing for gpx files to simulate. Here is how I overcame the problem:
I have deleted my app from the simulator
Under App->Capabilities enabled Background Modes->Location updates
Run the app and let it install on simulator
Allow access, and I was able to locate the user with GPX
Afterwards I disabled Location Updates.
I don't know why, but this did the trick for me.
I installed XCODE 6 the version form developer.apple (I think is the final one) and Im working my projects there (iOS 7 projects) but obviously brings iOS 8 SDK I really don't know if this affects the project.
I have a mapview and I want to show the user location but it's impossible!
Code:
#property (nonatomic, strong) CLLocationManager *manager;
- (void)viewDidLoad {
[super viewDidLoad];
[self.manager requestAlwaysAuthorization];
[self.manager requestWhenInUseAuthorization];
[self.mapview setDelegate:self];
self.mapview.showsUserLocation = YES;
[self.mapview setCenterCoordinate:self.mapview.userLocation.location.coordinate animated:YES];
}
I don't get the "App whants to use your current location...", The mapview shows some place in Africa without pin or anything.
You must init/alloc the CLLocationManager *manager
something like this:
// Create the core location manager object
_locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// for iOS 8, specific user level permission is required,
// "when-in-use" authorization grants access to the user's location
//
// important: be sure to include NSLocationWhenInUseUsageDescription along with its
// explanation string in your Info.plist or startUpdatingLocation will not work.
//
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
check Apple example https://developer.apple.com/library/prerelease/ios/samplecode/LocateMe/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007801
I want to make a simple IOS 6.0 application that shows the lat/lon on screen each time the location is changed. The ViewController files are pretty trivial.
I alloc a CCLocationManager objec, set its variables and start it.
didUpdateLocations is called once or twice and then it stops being fired, even if the iPhone is moved. If I press Home button and reopen the app, the data on screen is updated once or twice before it stops again.
At simulation it works fine but not on a real 3GS iPhone.
If I uncomment the start/stop inside didUpdateLocations and continuously stop and start the service, it works, but the battery gets drained in extreme rates.
Also, this is part of a much bigger project and didUpdateLocations must be called each time the location is changed.
ViewController.h
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController
#property (nonatomic , strong) CLLocationManager *locationManager;
#property (weak, nonatomic) IBOutlet UILabel *lbl;
#end
ViewConroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLHeadingFilterNone; // whenever we move
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.PausesLocationUpdatesAutomatically = NO;
[_locationManager startUpdatingLocation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = [locations lastObject];
_lbl.text=[NSString stringWithFormat:#"%lf %lf",newLocation.coordinate.latitude, newLocation.coordinate.longitude];
//[_locationManager stopUpdatingLocation];
//[_locationManager startUpdatingLocation];
}
#end
If there's any advice on what's wrong, I would welcome it, I have lost a week already without solving it.
BTW, I have tested various values for the _locationManager variables but without any chnage in the behaviour
Additional info:
application is authorized to use location services
application is in foreground
Few tips for similar issues as per my experience with location-based programming on iOS.
If it works on simulator, then it should work on actual device as
well.
Unlike simulator, the actual device will only give update when its receives new information from GPS.
There are many cases where you won't get enough/required updates on a device, like when you are in a building (or covered area)
Try testing the app in open space (GPS works much better in open space rather than room/house/large-building).
PS. I don't know how much you moved but just to let you know, moving few steps doesn't make sure you will get a new location update, try using it on some vehicle (bike/car/bus).
I had this problem too — the easiest fix is simply to duplicate the target. You can then delete the original target.
It seems the problem occurs with older Xcode projects, not newly created ones.
You can add this call to your code:
locationManager.stopUpdatingLocation()
I am using a custom BeaconManager delegate so that beacon ranging is not determined by the life-cycle of the view controller. Everything works great but every once in a while (1-2 days) beacon ranging will stop working and didRangeBeacons will never get called. The only way to fix this is for me to reset my iPhone, once I do this, it works perfectly. Below is the code that I am using. The basic flow is that when my ViewController calls ViewDidLoad it sends a notification back to the AppDelegate to tell it to start ranging for beacons, I never tell it to stop then because I want it to continue to range for beacons no matter where the user navigates to in the app. I'm wondering if my code is causing this or if this is just a bug with Bluetooth. Thanks for your help!
BeaconManager.m
#import "BeaconManager.h"
#import "AppDelegate.h"
#interface BeaconManager()<CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLBeaconRegion *beaconRegion;
#end
#implementation BeaconManager
+ (id)sharedManager
{
static BeaconManager *sharedBeaconManager = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedBeaconManager = [[self alloc] init];
});
return sharedBeaconManager;
}
- (id)init
{
self = [super init];
if(self)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
}
return self;
}
- (void)startBeaconMonitoring:(NSString*)forUUID
{
NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:forUUID];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:#"com.beacons.publicRegion"];
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void)stopBeaconMonitoring
{
//Stop the region monitoring
if(self.locationManager != nil && self.beaconRegion != nil) {
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
}
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
self.beacons = beacons;
if(self.delegate != nil) {
[self.delegate beaconManager:self didRangeBeacons:self.beacons];
}
}
#end
ViewController.m
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] postNotificationName:#"startRanging" object:nil userInfo:nil];
}
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(startRangingForZombies) name:#"startRanging" object: nil];
return YES;
}
- (void)startRanging
{
//Start the beacon region monitoring when the controller loads
BeaconManager *beaconManager = [BeaconManager sharedManager];
beaconManager.delegate = self;
[beaconManager startBeaconMonitoring:#"1234-54324-34242-34242-43243"];
}
We have received many reports at Radius Networks of phones stopping detecting iBeacons and requiring a reboot or turning Bluetooth off and back on again to resolve the situation. Folks have reported this on iPhone 4S, iPhone 5s, iPhone 5c and iPads.
I do not have any hard evidence that this is something that broke as of iOS 7.1, but the report frequency has gone way up since its release. The circumstantial evidence is therefore pretty strong.
When this phone gets into this state, the phone can still scan for bluetooth devices, and can still transmit as an iBeacon. It is therefore not a hardware problem with Bluetooth. Based on the available evidence, it is most likely a newly introduced bug in CoreLocation.
Actually, it's a known bug in iOS 7.1. It's strictly a software problem with the Bluetooth stack for the latest version of iOS. Bluetooth devices detection sometimes just stops working - unfortunately, it's the case for all iOS 7.1-compatible devices. The bug has already been reported to Apple, but as long as they do not issue a fix for that, the best solution is to just reboot the device.
If reboot doesn't help, there is handy guide at SmartRobotic on how to solve it: http://www.smartbotics.com/#!4-Tips-to-Fix-Bluetooth-Problems-After-iOS-71-Upgrade/c118r/031A86F6-C8E8-4768-B4FD-E6F83D9E4317
If you are experiencing Bluetooth connectivity issues after upgrading to iOS 7.1, give these 4 tips a try.
Shut down and restart - some people have reported that this is all that was needed to fix their device after the iOS 7.1 upgrade.
Toggle Bluetooth OFF and back ON - Swipe up to access Control Center and tap the Bluetooth icon, wait at least 30 seconds, then toggle it back on. This can often repair a device which is experiencing connection issues.
Kill (force quit) the offending app - Start by double clicking Home to launch the multitasking cards interface. Touch and hold the card for the app, then toss it up and away. This will force the app to quit and it will be fully reloaded the next time the app is opened.
Clear and reset your Bluetooth device pairing - Go to Settings>Bluetooth and tap on the (i) icon for the offending device. Tap on Forget this Device. Now you should be able to re-add and re-pair the Bluetooth hardware to your device. To clear all paired devices, go to Settings > General > Reset > Reset Network Settings and then set up your Bluetooth pairings again.
Hopefully these suggestions will resolve your Bluetooth connectivity problems.
Cheers.
Apple introduced important changes to Bluetooth LE in 7.1 but also broke something inside.
From my experiments:
iPhone 4S 7.x - iBeacons work like a charm
2 x iPhone 4S 7.1, 2 x iPhone 5 7.1 - works fine but require restarts from time to time (undeterministic).
It looks like system issue - a big one.
I have contacted Estimote - they know about it.
Interesting fact: You can't find beacons - even estimote demo app can't, delegate methods are not called but You can turn (broken)device into a beacon and it will be discovered by other devices.
Disclaimer: I currently work for sensorberg, we´re selling beacons and a SDK.
We´ve hat numerous reports of this bug as well. We asked all our customers to file a bug report with Apple. Here is a template that you can use: https://gist.github.com/anonymous/5283b6941e1f7d4e4461
I personally had the behaviour twice, once I was able to record it: https://www.youtube.com/watch?v=6a6IJzaxxJg Only restarting the device helped.
Continue to file Apple rdar bug reports!
I had the similar issue, but after some time of investigation I realized that it is wrong to call the startMonitoringForRegion(region) and startRangingBeaconsInRegion(region) after each other. That is what you (Patrick) do:
- (void)startBeaconMonitoring:(NSString*)forUUID {
NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:forUUID];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:#"com.beacons.publicRegion"];
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
Instead the startRangingBeaconsInRegion(region) should to be called in the locationManagerDelegate method locationManager(manager: CLLocationManager!, didDetermineState state: CLRegionState, forRegion region: CLRegion!) (In this case the Swift code). This was my solution.
It make sense, because the first step is to find any beacon in the region, the second one is to get specific information from the already monitored beacon.
MKMapViewDelegate mapView:didUpdateUserLocation: method is not called when running on the 5.0 simulator, even if all location permissions are given in the device settings.
With 4.3 it's working fine.
Any ideas?
I got the same thing after refactor to ARC.
First I had the following code in viewDidLoad;
CLLocationManager *lm =[[CLLocationManager alloc] init];
lm.delegate = self;
lm.desiredAccuracy = kCLLocationAccuracyBest;
[lm startUpdatingLocation];
I did the following in de headerfile
#interface ViewController : UIViewController <CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
#property(nonatomic, strong)CLLocationManager *locationManager;
And
#synthesize locationManager;
The code I change in viewDidLoad
locationManager =[[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
Check "setUserTrackingMode:animated:" and "userTrackingMode". Both are new in the iOS5. I had a similar problem and fixed it by setting MKUserTrackingModeFollow in the setUserTrackingMode function. I think the default tracking mode is MKUserTrackingModeNone and only calls mapView:didUpdateUserLocation once.
If your problem is that the mapView:didUpdateUserLocation is never called, then take a look at the options in the new xcode, right below the console outputs there's an icon like the gps icon in the ipad, which lets you simulate a location.
I know it's an old thread. I'll answer anyway, it might help others too.
I had similar problem with iOS 6. Which I was able to solve by setting the mapview delegate to self.
Like this:
[mapView setDelegate:self];
Make sure your ViewController.h has the MKMapViewDelegate along the lines:
#interface ViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>