I'am new in Objective-C world. I try developing simple location application on iOS 6.1 on simulator. But when i try simulate location it doesn't work at all. I don't receive any event, but delegate object is registered properly and PositionProvider is startUpdate.
What is wrong?
I have following code:
PositionProvider
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "LocationListener.h"
#interface PositionProvider : NSObject
{
#public
LocationListener<CLLocationManagerDelegate> *listener;
#protected
CLLocationManager *manager;
}
#pragma mark -
#pragma mark on/off
-(void) startUpdate;
-(void) stopUpdate;
#end
Implementation
#implementation PositionProvider
{
#private
CLLocation *lastLocation;
}
-(void) startUpdate{
manager = [[CLLocationManager alloc] init];
LocationListener *listener2 = [[LocationListener alloc]init];
manager.delegate = listener2;
manager.desiredAccuracy = kCLLocationAccuracyBest;
if(manager == nil)
NSLog(#"Manager is NULL");
if(listener == nil || manager.delegate == nil)
NSLog(#"Listener is NULL");
NSLog(#"startUpdate");
if ([CLLocationManager locationServicesEnabled]) {
NSLog(#"Location Services Enabled");
switch ([CLLocationManager authorizationStatus]) {
case kCLAuthorizationStatusAuthorized:
NSLog(#"We have access to location services");
break;
case kCLAuthorizationStatusDenied:
NSLog(#"Location services denied by user");
break;
case kCLAuthorizationStatusRestricted:
NSLog(#"Parental controls restrict location services");
break;
case kCLAuthorizationStatusNotDetermined:
NSLog(#"Unable to determine, possibly not available");
break;
default:
break;
}
}
else {
NSLog(#"Location Services Are Disabled");
}
[manager startUpdatingHeading];
[manager startUpdatingLocation];
}
-(void) stopUpdate{
}
#end
LocationListener
#interface LocationListener : NSObject<CLLocationManagerDelegate>
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;
#end
Implementation
#implementation LocationListener
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
// newLocation.coordinate;
NSLog(#"Logging Location");
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"Logging Location");
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus) status{
NSLog(#"Status");
}
#end
Have you tried
[manager setDelegate:listener2];
Alternatively, you may have a memory management issue. Try adding the dealloc method with a debugger-breakpoint and see if it gets called before you expected:
- (void)dealloc {
NSLog(#"Dealloc called");
self.locationManager = nil;
}
Related
I'm using core location library in iOS for finding beacons, I'm in beacon region and the didRangeBeacons callback is triggering but it is always returning an empty array of beacons.
Please find the attached sample code. I have beacon immediate to iPhone, but still, beacon region state is inside when app opened and immediately it is changed to outside state and we are getting an empty array in didRangeBeacons. I have included both NSLocationWhenInUseUsageDescription. The NSLocationAlwaysUsageDescription keys are in the info.plist. The application has location permission set to "always". I'm using both Estimote and Kontakt beacons. OS version is iOS 11.2.6, Device iPhone 5s, Xcode 9.2.
#import "CoreLocationViewController.h"
#interface CoreLocationViewController ()
{
CLLocationManager *locationManager;
CLBeaconRegion *beacon_region;
}
#end
#implementation CoreLocationViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"CoreLocationViewController viewDidLoad");
NSUUID *ProximityUUID = [[NSUUID alloc] initWithUUIDString:#"b94f62c8-1af4-11e8-accf-0ed5f89f718b"];
beacon_region = [[CLBeaconRegion alloc] initWithProximityUUID:ProximityUUID identifier:#"abqwercds"];
[beacon_region setNotifyEntryStateOnDisplay:YES];
[beacon_region setNotifyOnExit:YES];
[beacon_region setNotifyOnEntry:YES];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
if ([CLLocationManager locationServicesEnabled]){
NSLog(#"Location Services Enabled");
if(IS_OS_8_OR_LATER){
NSLog(#"We are in LocationServicesRequestViewController IS_OS_8_OR_LATER");
NSUInteger code = [CLLocationManager authorizationStatus];
NSLog(#"CLLocationManager authorizationStatus %lu",(unsigned long)code);
if (code == kCLAuthorizationStatusNotDetermined) {
NSLog(#"kCLAuthorizationStatusNotDetermined");
[locationManager requestAlwaysAuthorization];
}
}else{
NSLog(#"We are in LocationServicesRequestViewController IS_OS_8_BELOW");
}
}else{
NSLog(#"authorizationStatus ");
}
}
#pragma mark Location Manager Delegate methods
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error{
NSLog(#"locationManager Error %#",error);
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
NSLog(#"Status of location service is %d",status);
if ((status == kCLAuthorizationStatusAuthorizedAlways) || (status == kCLAuthorizationStatusAuthorizedWhenInUse)){
NSLog(#"location service status changed 1");
[locationManager startMonitoringForRegion:beacon_region];
[locationManager requestStateForRegion:beacon_region];
}else{
NSLog(#"location service status changed 2");
}
}
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
NSLog(#"CLLocationManager Beacon Region State Determine ");
switch (state) {
case CLRegionStateUnknown:
{
NSLog(#" CLLocationManager Region state is unknown %#",region);
[locationManager stopMonitoringForRegion:beacon_region];
break;
}
case CLRegionStateInside:
{
NSLog(#" CLLocationManager Region state is In-Side %#",region);
[locationManager startRangingBeaconsInRegion:beacon_region];
}
case CLRegionStateOutside:
{
NSLog(#" CLLocationManager Region state is Out-Side %#",beacon_region);
[locationManager stopMonitoringForRegion:beacon_region];
break;
}
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
NSLog(#" CLLocationManager Enter into Region %#",region);
[locationManager startRangingBeaconsInRegion:beacon_region];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"didExitRegion location manager %#",region );
[locationManager stopMonitoringForRegion:beacon_region];
}
-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region{
NSLog(#"CLLocationManager Beacon Monitoring Started for the region %#",region);
}
-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error{
NSLog(#"CLLocationManager Monitoring of beacon region %# is failed, Error %#",region,error);
}
-(void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error{
NSLog(#"CLLocationManager ranging of beacon region %# is failed, Error %#",region.proximityUUID,error);
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
NSLog(#"beacons %#",beacons);
}
Why I can get the direction but I can't get the latitude and longitude?
Do I need to get user's location information admission and write in my code?
Here's my code
#import "ViewController.h"
#interface ViewController ()<CLLocationManagerDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager startMonitoringSignificantLocationChanges];
[self.locationManager startUpdatingLocation];
[self.locationManager startUpdatingHeading];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[self.locationManager stopUpdatingLocation];
self.Lat.text = [NSString stringWithFormat:#"%f", manager.location.coordinate.latitude];
NSLog(#"%f",manager.location.coordinate.longitude);
self.Long.text = [NSString stringWithFormat:#"%f", manager.location.coordinate.longitude];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
self.Mag_heading.text = [NSString stringWithFormat:#"%f",newHeading.magneticHeading];
self.True_heading.text = [NSString stringWithFormat:#"%f", newHeading.trueHeading];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Once configured, the location manager must be "started"
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];
}
you have to replace below code.
Use newLocation instead of manager
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
self.Lat.text = [NSString stringWithFormat:#"%f", newLocation.coordinate.latitude];
NSLog(#"%f",newLocation.coordinate.latitude);
self.Long.text = [NSString stringWithFormat:#"%f", newLocation.coordinate.longitude];
[self.locationManager stopUpdatingLocation];
}
Since the new iOS 8 beta release, I have not been able to successfully get a user's location. Prior to the update to iOS 8 I had no issues, but now it always returns 0.000000 as the current latitude and longitude. Is this just a bug in the new release? My code is listed below:
//from the .h file
#interface MasterViewController : PFQueryTableViewController<CLLocationManagerDelegate,UITextFieldDelegate, UISearchBarDelegate, UISearchDisplayDelegate> {
}
#property (nonatomic, strong) CLLocationManager *locationManager;
//from the .m file
#synthesize locationManager = _locationManager;
- (void)viewDidLoad {
[super viewDidLoad];
[self.locationManager startUpdatingLocation];
}
- (CLLocationManager *)locationManager {
if (_locationManager != nil) {
return _locationManager;
}
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
return _locationManager;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
}
UPDATE
This question has been answered (Location Services not working in iOS 8). For anyone still struggling with this, to maintain backwards compatibility with iOS 7, I used the code below:
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) { }
As mentioned in your update/comment, iOS8 requires you to use requestAlwaysAuthorization or requestWhenInUseAuthorization as well as a new NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist
But there is something else which is wrong in your code:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
It has been deprecated in iOS6 and you should now use this new delegate method instead:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
You can then get the latest location with something like this:
CLLocation *newLocation = [locations lastObject];
I've heard time and time again that there is always a better pattern than the singleton, but I can't understand how else my application could access the device location without waiting for the GPS to return data (I'm assuming that the location system is only running when explicitly called for, correct me if wrong).
So is there a better pattern for accessing CLLocation data from multiple (unrelated) controllers? Or can I expect the device location to be updating in the background even if I am not accessing it through a CLLocationManager?
Declare a single class . Like the following .
MyLocation.h
#protocol MyCLControllerDelegate <NSObject>
- (void)locationUpdate:(CLLocation *)location;
- (void)locationError:(NSError *)error;
#end
#interface MyLocation : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
id delegate;
}
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) id <MyCLControllerDelegate> delegate;
MyLocation.m
#import "MyLocation.h"
#implementation MyLocation
#synthesize locationManager;
#synthesize delegate;
- (id) init {
self = [super init];
if (self != nil) {
if([CLLocationManager locationServicesEnabled]) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted )
{
[self showAlertWithTitle:#"Warning" andWithMessage:#"Determining your current location cannot be performed at this time because location services are enabled but restricted" forTargetView:self];
NSlog(#"Determining your current location cannot be performed at this time because location services are enabled but restricted");
}
else
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self; // send loc updates to myself
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kThresholdDistance];
[self.locationManager startUpdatingLocation];
NSLog(#"Location sharing set ON!");
}
} else {
[MobileYakHelper showAlertWithTitle:#"Error" andWithMessage:#"Determining your current location cannot be performed at this time because location services are not enabled." forTargetView:self];
NSLog(#"Location sharing set OFF!");
}
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSDictionary *dictValue = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:newLocation.coordinate.latitude], #"latitude",
[NSNumber numberWithDouble:newLocation.coordinate.longitude], #"longitude",
nil];
[[NSUserDefaults standardUserDefaults] setValue:dictValue forKey:#"MY_LOCATION"];
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
if (meters >= kThresholdDistance ) {
[self.delegate locationUpdate:newLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
[self.delegate locationError:error];
}
#end
To use it in few controller .Adapt delegate in it's .h file and use like as follows :
- (void) initializeLocations
{
MyLocation _myLocation = [[MyLocation alloc] init];
_myLocation.delegate = self;
_myLocation.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
CLLocation * currentLocation = _myLocation.locationManager.location;
// Updating user's current location to server
[self sendUserCurrentCoordinate:currentLocation.coordinate];
// start updating current location
_myLocation.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[_myLocation.locationManager startUpdatingLocation];
[_myLocation.locationManager startUpdatingLocation];
}
- (void)locationUpdate:(CLLocation *)location {
NSLog(#"location %#", location);
}
- (void)locationError:(NSError *)error {
NSLog(#"locationdescription %#", [error description]);
}
I have the following code:
- (void) viewWillAppear {
[self startSignificantChangeUpdates];
}
- (void)startSignificantChangeUpdates
{
if ([CLLocationManager locationServicesEnabled])
{
NSLog(#"start significant changes");
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startMonitoringSignificantLocationChanges];
}
}
problem is that the location manage is not calling its delegate function
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
What can I do?
In your .h file:
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate>
In your .m file:
#implementation ViewController {
// This is a private variable, used within this file only
CLLocationManager *locationManager;
}
-(void)viewDidLoad {
locationManager = [[CLLocationManager alloc] init];
}
-(void)viewWillAppear {
// If the delegate is still not being set, try putting this code into viewDidAppear
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
-(void)locationManger:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"didFailWithError: %#", error);
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSLog(#"didUpdateToLocation: %#", [locations lastObject]);
CLLocation *currentLocation = [locations lastObject];
[locationManager stopUpdatingLocation];
}
For more information about getting the user's location, look at this guide, which I used to implement location into an app of mine: http://www.appcoda.com/how-to-get-current-location-iphone-user/
How are you testing this? If you are running this in the simulator, you can go to Debug->Location->Freeway Drive. You can put a break point in locationManager:didUpdateToLocation method or even put a log statement to log the current location coordinates. You should see it work.
Please replace this line
[locationManager startMonitoringSignificantLocationChanges];
with this code
[locationController.locationManager startUpdatingLocation];
and then check
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
}