我正在开发基于地图和位置跟踪的iOS应用。当用户首次启动应用程序时,它会要求获得跟踪位置等的权限。唯一的问题是,当它正在这样做时,我有代码设置初始地图视图和其他基于位置的变量,然后用户单击确定。
我发现我可以在等待用户更改位置管理器权限的while循环之后执行这些启动步骤,但这不可能是最佳做法,更不用说它会导致一些奇怪的行为启动画面和地图之间的过渡:
BOOL firstrun = TRUE;
while ([[locationManager class] authorizationStatus] == kCLAuthorizationStatusDenied || [[locationManager class] authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
NSLog(@"Waiting for location permission");
}
...initiation code...
警报框是否有“位置访问授予”监听器或者我不知道的位置管理器委托中的类似功能?我在文档中看不到这样的方法。谁知道最好的做法是什么?非常感谢你。
修改 我按如下方式开始我的位置跟踪:
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
[locationManager startMonitoringSignificantLocationChanges];
self.musicmap.delegate = self;
[self.mymap setShowsUserLocation:true];
由于
答案 0 :(得分:8)
我建议您将类设为CLLocationManagerDelegate,然后实现此方法:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
//Your code goes here
}
可以找到有关CLLocationManagerDelegate的更多信息here。
希望有所帮助!
答案 1 :(得分:4)
我的应用程序和应用程序在用户有时间接受或拒绝位置权限对话之前做了类似的问题。这就是我最终要做的事情。
-(BOOL)locationAuthorizationStatus {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
// user has not authorized us to use location
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Location Denied", @"Location Denied")
message:NSLocalizedString(@"This app does not have permission to access your location. Please enable location access in device settings.", @"Message stating this app does not have permission to access your location and to enable location permission in settings")
delegate:self
cancelButtonTitle:NSLocalizedString(@"Ok", @"Ok")
otherButtonTitles: nil];
[alert show];
return NO;
}
// Check if region monitoring is available for this device
if (![CLLocationManager regionMonitoringAvailable]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Geofencing Unavailable", @"Geofencing Unavailable")
message:NSLocalizedString(@"This device is not able to monitor regions", @"Message stating this device is not able to monitor regions")
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(@"Ok", @"Ok"), nil];
[alert show];
return NO;
} else {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
// trigger a location check to prompt user for authorization
LocationManagerController *locationController = [LocationManagerController sharedManager];
[locationController.locationManager startUpdatingLocation];
// the dialogue box is triggered here
[locationController.locationManager stopUpdatingLocation];
_waitingOnAuthorization = YES;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkForAuthorizationStatusChange) name:@"WaitingOnAuthorizationStatus" object:nil];
return NO;
}
}
return YES;
}
-(void)checkForAuthorizationStatusChange {
if (_waitingOnAuthorization) {
// this should only catch location change on first time
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) {
// user approved location services
} else {
// user declined authorization
}
// set flag back to NO
_waitingOnAuthorization = NO;
}
// remove our notification observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
您必须添加适用于您的用例的变量。但这是它的要点。
Apple没有任何委托方法可以捕获这个选择,所以唯一的解决方法就是hacky。这种方法对我来说效果很好。稍微hacky,但工作。希望这会有所帮助。
答案 2 :(得分:0)
//Start up motion manager, not sure if you need this for location manager
motionManager = [[CMMotionManager alloc] init];
if (motionManager.accelerometerAvailable) {
motionManager.accelerometerUpdateInterval = 1.0/2.0;
[motionManager startAccelerometerUpdates];
}
locationManager = [[CLLocationManager alloc] init];
//We will be the location manager delegate
locationManager.delegate = self;
//Track position at the 100m accuracy
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
//We want to see all location updates, regardless of distance change
locationManager.distanceFilter = 0.0;
[locationManager startUpdatingLocation];
将上面的内容放在“viewDidLoad”或appDelegate“didFinishLaunchingWithOption”中
以下内容处理更新和内容。 bestLocation是一个CLLocation。您需要实现CLLocationManagerDelegate。 TWO_MINUTES = 120
- (BOOL)isBetterLocation:(CLLocation *)location {
if (bestLocation == nil){
//best location not set yet, so it's a better location by default
return YES;
}
// Figure out how long it's been since we got a better location
NSTimeInterval timeDelta = [location.timestamp timeIntervalSinceDate:bestLocation.timestamp];
BOOL isSignificantlyNewer = timeDelta > TWO_MINUTES;
BOOL isSignificantlyOlder = timeDelta < -TWO_MINUTES;
BOOL isNewer = timeDelta > 0;
if (isSignificantlyNewer) {
return YES;
}else if (isSignificantlyOlder) {
return NO;
}
CLLocationAccuracy accuracyDelta = location.horizontalAccuracy - bestLocation.horizontalAccuracy;
//You want accuracy to be low
BOOL isLessAccurate = accuracyDelta > 0;
BOOL isMoreAccurate = accuracyDelta < 0;
BOOL isDifferent = location.coordinate.latitude != bestLocation.coordinate.latitude ||
location.coordinate.longitude != bestLocation.coordinate.longitude;
if (isMoreAccurate) {
return YES;
} else if (isNewer && !isLessAccurate && isDifferent) {
return YES;
}
return NO;
}
#pragma mark - Location manager delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if ([self isBetterLocation:newLocation]){
self.bestLocation = newLocation;
} else {
[locationManager stopUpdatingLocation];
isLocating = NO;
NSLog(@"AppDelegate: Turning off location manager >>>>>>>>>>>>>>>>>>>>>");
}
}
注意:您不需要“isBetterLocation”方法。这将只检查位置并在2分钟后关闭位置管理器,这样您就不会磨损用户的电池。有时您不希望经理关闭,所以如果您愿意,可以将其留下。
我不知道你已经做了多少。这就是我做的方式。