iOS等待位置管理器初始化

时间:2012-12-20 22:37:21

标签: ios map location cllocationmanager

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

由于

3 个答案:

答案 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];
}

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

  1. 通过BOOL方法(locationAuthorizationStatus)检查授权状态
  2. 如果可以使用位置,则返回YES执行任何您想要的操作
  3. 如果没有,则返回NO并提醒用户
  4. 如果是第一次,将启动位置管理器以触发位置对话,然后停止它以节省电池,设置标志并设置通知,以便您知道用户何时点击是或否。
  5. 通知会触发方法checkAuthorizationChangeStatus并重新检查权限以查看用户执行的操作。从那里,您可以根据用户的选择调用您需要的任何方法。
  6. 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分钟后关闭位置管理器,这样您就不会磨损用户的电池。有时您不希望经理关闭,所以如果您愿意,可以将其留下。

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