web-dev-qa-db-ja.com

CLLocationManagerと精度の問題-何か経験はありますか?

だから私はiPhoneGPSのいくつかの精度の問題に取り組んでいます。ロケーションを利用したアプリがあります。

デリゲートメソッドlocationManager: didUpdateToLocation: fromLocation:で場所が返されます。少し調べてみると、desiredAccuracyプロパティをkCLLocationAccuracyBestに設定した場合でも、GPSが最初に返す結果が常に正確であるとは限らないようです。

これを回避するために、少なくとも3回newLocation:が返される前にstopUpdatingLocationを呼び出さないでください(これは非常に高速です)。また、stopUpdatingLocationを実行してnewLocationを返すかどうかに関する他の2つの「要件」を試してみました。私が試した1つの方法は、newLocationの緯度と経度を確認してoldLocationと比較し、これらが同一でない場合は、場所の更新を実行し続けることでした。また、oldLocationnewLocationの間の距離を確認してみましたが、20メートル未満であれば問題ありません。これらは両方とも、少なくとも3回の実行を返すことでテストされます。後者の方法は、ユーザーが移動中の車両に乗っている場合、newLocationoldLocationが100%同一であるために逃げるのが非常に難しいため、それほど「厳密」ではありません。

さて、私の問題は、上記を行った場合でも(基本的に場所を受け入れず、CLLocationManagerでいくつかの更新が発生し、CLLocations間の距離をチェックするまで(またはそれらが同一であるかどうか) )テスト時に、場所について多少奇妙な結果が表示されることがあります。

アプリを終了し、Maps.appにアクセスし、GPSを使用してマルチタスクを開き、アプリを強制終了してから再度開いてクリーンな起動を行うと、修正されることがあります。

同じ種類の問題を回避するために人々が使用した経験と可能な解決策はありますか?コメントと解決策を高く評価します:)

27
runmad

次のコードを取得したのがどのプロジェクトであったかは正確には覚えていませんが、これは非常にうまく機能しました(WWDC 2010ビデオからのものだったことを覚えています)。私のコードでは、元のプロジェクトからのコメントをそのまま残したので、これが役立つことを願っています。

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    // test the age of the location measurement to determine if the measurement is cached
    // in most cases you will not want to rely on cached measurements
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];

    if (locationAge > 5.0) return;

    // test that the horizontal accuracy does not indicate an invalid measurement
    if (newLocation.horizontalAccuracy < 0) return;

    // test the measurement to see if it is more accurate than the previous measurement
    if (bestEffortAtLocation == nil || bestEffortAtLocation.horizontalAccuracy > newLocation.horizontalAccuracy) {
        // store the location as the "best effort"
        self.bestEffortAtLocation = newLocation;

        // test the measurement to see if it meets the desired accuracy
        //
        // IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue 
        // accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of 
        // acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout.
        //
        if (newLocation.horizontalAccuracy <= locationManager.desiredAccuracy) {
            // we have a measurement that meets our requirements, so we can stop updating the location
            // 
            // IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible.
            //
            [self stopUpdatingLocation:NSLocalizedString(@"Acquired Location", @"Acquired Location")];

            // we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpdatingLocation:) object:nil];
        }
    }
}

お役に立てれば!

経由GetLocationViewController.mAppleの「LocateMe」サンプルプロジェクトで、次の場所で入手できます。

https://developer.Apple.com/library/content/samplecode/LocateMe/Introduction/Intro.html

45
donkim

ドンキムの答えから、この行を置き換えることを検討してください

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpdatingLocation:) object:nil];

ライン付き

[NSObject cancelPreviousPerformRequestsWithTarget: self];
0
M.Y.