7

私は地図と位置追跡に基づいてiOSアプリを開発しています。ユーザーが最初にアプリを起動すると、場所などを追跡する許可を求められます。唯一の問題は、それを実行している間、ユーザーが[OK]をクリックする前に、初期マップビューとその他のロケーションベースの変数を設定するコードを持っていることです。

ユーザーがロケーションマネージャーの権限を変更するのを待つ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にはこの選択をキャッチするためのデリゲートメソッドがないので、それを回避する唯一の方法はちょっとハッキーです。この方法は私にとってはうまくいきました。少しハッキーですが、動作します。お役に立てれば。

于 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を実装する必要があります。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分ほど後に場所マネージャーをオフにするので、ユーザーのバッテリーを消耗することはありません。ただし、マネージャーをオフにしたくない場合もあるので、必要に応じてマネージャーを省略できます。

あなたがこれをどれだけやったかはわかりません。これが私がやった方法です。

于 2012-12-20T23:00:48.110 に答える