I'm wondering if it's problematic to implement two different SDK's that use CLLocationManager functionality in one app.
Both SDK's are monitoring CLBeaconRegions, and both have implemented different classes with CLLocationManager instances and delegate implementations.
Possible problems:
What if one of the SDK's removes all monitored CLBeaconRegions from it's CLLocationManager. Does that influence the other SDK's CLLocationManager as well?
What if both SDK's start looking for the same UUID (but with a different CLBeaconRegion identifier)... do both get a delegate call?
I can't think of any other reason why this shouldn't work, but maybe I'm missing something?
Have you tried with Shared Instance ?
What you can do is try to manage your code with same location manager instance.
So any change in delegate may reflect in single class from there you can manage you code .
Example :-
.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationManager : NSObject <CLLocationManagerDelegate>
#property (nonatomic,strong) CLLocationManager *objLocationManager;
#property (nonatomic,assign) CLLocationCoordinate2D currentcoordinate;
+ (LocationManager *) SharedInstance;
+ (CLLocation *) currentLocation;
#end
.m
#define currentCordinates [LocationManager SharedInstance].currentcoordinate
#define currentLocationmanger [LocationManager SharedInstance].objLocationManager
// Shared Manager
static LocationManager *SharedInstance = nil;
+ (LocationManager *) SharedInstance
{
#synchronized(self)
{
if (SharedInstance == nil)
{
SharedInstance = [[super allocWithZone:NULL] init];
currentLocationmanger = [[CLLocationManager alloc]init];
currentLocationmanger.delegate = [LocationManager SharedInstance];
/* Pinpoint our location with the following accuracy:
*
* kCLLocationAccuracyBestForNavigation highest + sensor data
* kCLLocationAccuracyBest highest
* kCLLocationAccuracyNearestTenMeters 10 meters
* kCLLocationAccuracyHundredMeters 100 meters
* kCLLocationAccuracyKilometer 1000 meters
* kCLLocationAccuracyThreeKilometers 3000 meters
*/
currentLocationmanger.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
/* Notify changes when device has moved x meters.
* Default value is kCLDistanceFilterNone: all movements are reported.
*/
currentLocationmanger.distanceFilter = 2.0f;
/* Notify heading changes when heading is > 5.
* Default value is kCLHeadingFilterNone: all movements are reported.
*/
currentLocationmanger.headingFilter = 5;
[LocationManager SharedInstance].geocoder = [[CLGeocoder alloc] init];
[[LocationManager SharedInstance].objLocationManager startUpdatingLocation];
// update location
if ([CLLocationManager locationServicesEnabled]){
[currentLocationmanger startMonitoringSignificantLocationChanges];
}
}
}
return SharedInstance;
}
//other delgates and stuff to manage in .m
Some where in when you use is use with shared intace
//region.span = span;
region.center = [LocationManager SharedInstance].currentcoordinate;
Related
I have searched a lot and didn't get any satisfactory answer, I have a scenario where I am showing a list of sellers based on user's current location. I am getting a location for the first time and when I run my App afterward whenever I try to get the location I am getting a cache location data. I did try after some time even after every 24 hours but still getting the cache location where my current location is changed as well. Following is the code I am using for reference. please advise.
Property defined in Header file
#property (nonatomic,retain) CLLocationManager *locationManager;
- (void)startSingleLocationRequest
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[self.locationManager startUpdatingLocation];
[self.locationManager requestWhenInUseAuthorization];
}
#pragma mark --didUpdateLocations
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
self.latitudeValue = locations.lastObject.coordinate.latitude;
self.longitudeValue = locations.lastObject.coordinate.longitude;
// location set for simulation to UK
if(self.latitudeValue != 51.509979 && self.longitudeValue != -0.133700){
[MBProgressHUD hideHUDForView:self.outletSearchNearBy animated:YES];
[self.locationManager stopUpdatingLocation];
abc *slv =[self.storyboard instantiateViewControllerWithIdentifier:#"abc"];
slv.receivedLatitudeValue = self.latitudeValue;
slv.receivedLongitudeValue = self.longitudeValue;
[self.navigationController pushViewController:slv animated:YES];
}
else{}
}
You can do something like,
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
for(int i=0;i<locations.count;i++){
CLLocation * newLocation = [locations objectAtIndex:i];
CLLocationCoordinate2D theLocation = newLocation.coordinate;
CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0)
{
continue;
}
// do your all stuff here and then
break;
}
}
Your code will not executes if your location age is more than 5 seconds. You can decide location age lie 10 seconds or 20 seconds!
Update :
Just replace your property declaration
#property (nonatomic,retain) CLLocationManager *locationManager;
with
#property (nonatomic,strong) CLLocationManager *locationManager;
or
just declare it as instance variable like,
CLLocationManager *locationManager;
and remove self from avery instance of it!
Second thing,
You should do first,
[self.locationManager requestWhenInUseAuthorization];
and then start update of location,
[self.locationManager startUpdatingLocation];
Can you try like this
self.locationManager.pausesLocationUpdatesAutomatically = NO;
Because it
Specifies that location updates may automatically be paused when possible.
By default, this is YES for applications linked against iOS 6.0 or later.
On the other hand, kCLLocationAccuracyBestForNavigation uses top speed GPS. So better to use this instead of kCLLocationAccuracyNearestTenMeters.
Lion thanks for the support, actually i was checking location inside the plaza and due to that i was not getting the right location, i tested by coming outside and it is showing perfectly. anyways thanks lion you have been really helpful.
I need to pick coordinates of current marker position on Google maps. It should update coordinates as marker is moving on map.
I'm using GoogleMaps , GooglePlaces and GooglePlacePicker API's. I can get nearby places using GooglePlacePicker API but I want to pick exact coordinates of location where marker is present.
It is already done in Uber?
Use this,
.h
#interface ViewController : UIViewController <CLLocationManagerDelegate> {
GMSMapView *mapView_;
GMSMarker *marker_;
float currentLatitude;
float currentLongitude;
}
#property(nonatomic,retain) CLLocationManager *locationManager;
#property (nonatomic)CLLocationCoordinate2D coordinate;
.m
- (void)viewDidLoad {
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
[_locationManager setDelegate:self];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if (IS_OS_8_OR_LATER) {
if ([_locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[_locationManager requestWhenInUseAuthorization];
}
}
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSLog(#"%#",locations);
CLLocation *currentLoc=[locations objectAtIndex:0];
NSLog(#"CurrentLoc : %#",currentLoc);
_coordinate=currentLoc.coordinate;
currentLatitude = currentLoc.coordinate.latitude;
currentLongitude = currentLoc.coordinate.longitude;
}
-(void)plotMarkerForLatitude:(float)latitude andLongitude:(float)longitude {
// Now create maker on current location
if (marker_ == NULL) {
marker_ = [[GMSMarker alloc] init];
}
CLLocationCoordinate2D target =
CLLocationCoordinate2DMake(latitude, longitude);
marker_.position = target;
marker_.title = #"title";
marker_.appearAnimation = kGMSMarkerAnimationPop;
NSLog(#"%f %f",latitude,longitude);
marker_.icon = [UIImage imageNamed:#"marker"];
marker_.snippet = #"Address";
marker_.map = mapView_;
}
In Plist :
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow access to get your current location</string>
This can possibly be done by implementing the GMSMapViewDelegate protocol. See the guide to events and the list of methods on the GMSMapViewDelegate.
As mentioned in the documentation,
Applications can use this event to trigger a refresh of markers or other content being displayed on the GMSMapView, rather than, for example, reloading the content on every camera change.
You may also check Google Maps SDK for iOS for more information on what other APIs you can use along with Maps iOS SDK to build location-relevant apps and sites.
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).
I'm getting my location position from the iPhone's GPS. I want to get the coordinate from the same point 15 times (to get the best horizontal accuracy).
Is there a way to wait for example, 2 seconds between one coordinate and another?
I use an object called coordinate, with latitude and longitude as property.
.... Exemple code
Coordinate * coord = [[Coordinate alloc] init];
NSMutableArray *coordinates = [[NSMutableArray alloc] init];
for (i=0 ; i<=14; i++)
{
coord = newlocation;
[coordinates addObject:coord];
.... some code to wait 2 seconds before add a new object to the array....
}
I tried to use NSThread sleepfortimeinterval, but the view freezes.
Thanks
Rather than having a for loop like this, you could theoretically use a repeating NSTimer that fired every two seconds, and then invalidate the timer after 15 iterations.
But I'd not suggest doing that, but rather shift to an event-driven model, waiting for calls to your didUpdateLocations. There's no point in checking in two seconds, if didUpdateLocations hasn't been updated. Likewise, there's no point in repeatedly checking 15 times over 30 seconds if, for example, you get a really accurate location after 5 seconds.
I'd suggest start monitoring the location, watch the locations as they come in with subsequent calls to didUpdateLocations, and examine horizontalAccuracy of the CLLocation (which tells you how accurate the location is). Once you reach the desired horizontalAccuracy, you can declare success (e.g. stop monitoring locations or whatever). You could also establish a NSTimer that automatically turned off the monitoring of locations after 30 seconds, if you want, as well.
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%s", __PRETTY_FUNCTION__);
[self startStandardUpdates];
// after 30 seconds, if we haven't found a location, declare success with whatever we got (if anything)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self stopStandardUpdates]; // stop monitoring location if you want
if (!self.foundLocation) {
if (self.bestLocation) {
NSLog(#"Didn't find perfect location, but location has accuracy of %.1f meters", self.bestLocation.horizontalAccuracy);
} else {
NSLog(#"Even after 30 seconds, did not find any locations!");
}
}
});
}
#pragma mark - Location Services
- (void)startStandardUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == self.locationManager)
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Set a movement threshold for new events.
self.locationManager.distanceFilter = 5;
[self.locationManager startUpdatingLocation];
}
- (void)stopStandardUpdates
{
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* location = [locations lastObject];
NSLog(#"%s: horizontalAccuracy = %.1f", __FUNCTION__, location.horizontalAccuracy);
if (location.horizontalAccuracy < 0) // not a valid location
return;
// this checks to see if the location is more accurate than the last;
// or you might just want to eliminate this `if` clause, because if
// you get updated location, you can probably assume it's better than
// the last one (esp if the user might be moving)
if (!self.bestLocation || location.horizontalAccuracy <= self.bestLocation.horizontalAccuracy) {
self.bestLocation = location;
}
if (location.horizontalAccuracy <= 5) { // use whatever you want here
NSLog(#"Found location %#", location);
self.foundLocation = YES;
[self stopStandardUpdates]; // stop it if you want
}
}
This uses the following properties:
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation *bestLocation;
#property (nonatomic) BOOL foundLocation;
The following code results in null coordinates. The weird thing is the UIAlert prompting the app to use current location appears briefly before the user can select yes.
My code which i have used :
CLLocationManager *locationManager;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
float latitude = locationManager.location.coordinate.latitude;
float longitude = locationManager.location.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
The NSLog prints 0.0000000 for both coordinates.
Thanks!
The reason you're getting 0 is because the location manager hasn't collected any data at that point (it has started thought)
You need to set your class as the delegate of the location manager (ie supplying a function that is called whenever a new location is retrieved), and also retain your location manager.
// Inside .m file
#interface MyClass () <CLLocationManagerDelegate> // Declare this class to implement protocol CLLocationManagerDelegate
#property (strong, nonatomic) CLLocationManager* locationManager; // Retains it with strong keyword
#end
#implementation MyClass
// Inside some method
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
// Delegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation* loc = [locations lastObject]; // locations is guaranteed to have at least one object
float latitude = loc.coordinate.latitude;
float longitude = loc.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
}