7

我正在开发基于地图和位置跟踪的 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];

谢谢

4

3 回答 3

8

我建议将您的类设为 CLLocationManagerDelegate,然后实现此方法:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    //Your code goes here
}

更多关于 CLLocationManagerDelegate 的信息可以在这里找到。

希望有帮助!

于 2013-01-02T21:33:31.930 回答
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];
}

您必须添加适用于您的用例的变量。但这里是它的要点。

  1. 通过 BOOL 方法检查授权状态 (locationAuthorizationStatus)
  2. 如果可以使用位置,返回 YES 做任何你想做的事
  3. 如果不是,则返回 NO 并提醒用户
  4. 如果第一次,将启动位置管理器以触发位置对话,然后停止它以节省电池,设置标志并设置通知,以便您知道用户何时点击是或否。
  5. 该通知触发方法 checkAuthorizationChangeStatus 并重新检查权限以查看用户做了什么。从那里,您可以根据用户的选择调用您需要的任何方法。

Apple 没有任何委托方法来捕捉这个选择,所以唯一的方法是有点 hacky。这种方法对我来说效果很好。有点hacky,但有效。希望这可以帮助。

于 2013-01-02T21:24:06.417 回答
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。两分钟 = 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 分钟后关闭位置管理器,这样您就不会耗尽用户的电池。有时您不希望经理离开,因此您可以根据需要将其排除在外。

我不知道你已经做了多少。我就是这样做的。

于 2012-12-20T23:00:48.110 回答