9

私はdistanceFromLocation:メソッドを使用して、iPhoneを手に持って歩いている合計距離を計算しようとしています。これまでのところ、私は混乱し、不正確で、一見恣意的な結果を修正するために、あらゆる場所を検索してきました。これらのコードスニペットでは、theLabelはアプリのインターフェースに存在する単なるラベルオブジェクトであり、distanceMovedは私が歩いた合計距離を保存しようとしている変数であり、locManは@interfaceファイルで宣言されているロケーションマネージャーです。 。

- (void)viewDidLoad
{
   locMan = [[CLLocationManager alloc] init];
   locMan.delegate = self;
   [locMan startUpdatingLocation];
   isInitial = true;
   distanceMoved = 0.0;
   [super viewDidLoad];
}

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
   distanceMoved += [newLocation distanceFromLocation: oldLocation];
   theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
}

私がここで間違っていることを修正するための助けをいただければ幸いです。ありがとうございました!

4

4 に答える 4

14
  1. キャッシュされた(古い)位置データを除外し、
  2. 無効な場所の結果(精度<0)を除外し、
  3. 精度要件をに設定しますkCLLocationAccuracyBest
  4. 位置ノイズを除去するために、最小距離フィルター、できれば少なくとも10メートルを設定します。
  5. 編集oldLocation:がnilの場合、距離を計算しないでください。

できることは他にもありますが、十分なhorizo​​nalAccuracy(<30m)が得られれば、これは機能するはずです。精度の低い結果を除外することもできますが、その場合は、もう少し複雑なoldLocationを自分で追跡する必要があります。

NSLog(以下を参照)を追加して、何が起こっているかを確認できるようにします。それでも良い結果が得られない場合は、NSLogの出力を投稿して、何が起こっているのかを確認し、さらに支援できるようにしてください。

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 

    if (age > 120) return;    // ignore old (cached) updates

    if (newLocation.horizontalAccuracy < 0) return;   // ignore invalid udpates

    // EDIT: need a valid oldLocation to be able to compute distance
    if (oldLocation == nil || oldLocation.horizontalAccuracy < 0) return; 

    CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation];

    NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
        oldLocation.coordinate.latitude,
        oldLocation.coordinate.longitude,
        newLocation.coordinate.latitude,
        newLocation.coordinate.longitude, 
        distance,
        newLocation.horizontalAccuracy);

    distanceMoved += distance;
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
}

- (void)viewDidLoad
{
   locMan = [[CLLocationManager alloc] init];
   locMan.delegate = self;
   locMan.desiredAccuracy = kCLLocationAccuracyBest;
   locMan.distanceFilter = 10;

   [locMan startUpdatingLocation];
   isInitial = true;
   distanceMoved = 0.0;
   [super viewDidLoad];
}

didUpdateLocationsを使用して同じことをしたい場合は、iOS6用に編集してください:(上記のメソッドは非推奨になっているため)最も簡単な解決策は、プロパティ内の各場所を保存して、次の更新時に前の場所を取得することです。oldLocation:を保持するクラスのプロパティを宣言します。

@property (nonatomic, retain) CLLocation* oldLocation;

次に、デリゲートメソッドで、次にデリゲートメソッドが呼び出されたときにnewLocation使用するために、それぞれを保存します。oldLocation

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocations:(NSArray *)locations
{
    CLLocation* newLocation = [locations lastObject];

    NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 

    if (age > 120) return;    // ignore old (cached) updates

    if (newLocation.horizontalAccuracy < 0) return;   // ignore invalid udpates

    // EDIT: need a valid oldLocation to be able to compute distance
    if (self.oldLocation == nil || self.oldLocation.horizontalAccuracy < 0) {
        self.oldLocation = newLocation;
        return; 
    }

    CLLocationDistance distance = [newLocation distanceFromLocation: self.oldLocation];

    NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
        self.oldLocation.coordinate.latitude,
        self.oldLocation.coordinate.longitude,
        newLocation.coordinate.latitude,
        newLocation.coordinate.longitude, 
        distance,
        newLocation.horizontalAccuracy);

    distanceMoved += distance;
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];

    self.oldLocation = newLocation;    // save newLocation for next time
}
于 2012-04-17T20:00:28.837 に答える
0

ロケーションマネージャーの精度を設定していません。アップルのドキュメントを確認してください。これは、accuracy=bestfornavigationのようなものです。か何か。それは地獄のようにバッテリーを消耗するはずですが、この種の目的のためのものです。

編集:私が手元に持っていたことを思い出しました。

// Create the Location Manager
locationManager = [[CLLocationManager alloc] init];

// Configure the Location Manager
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
于 2012-04-17T03:55:21.620 に答える
0
CLLocationDistance distance = [secondLocation distanceFromLocation:firstLocation];  // distance is expressed in meters

CLLocationDistance kilometers = distance / 1000.0;
// or you can also use this..
CLLocationDistance meters = distance;

NSString *distanceString = [[NSString alloc] initWithFormat: @"%f", kilometers];

flot totaldistancecovered = [distanceString floatValue];

//Now,you can use this float value for addition...
// distanceMoved  should be float type variable which is declare in .h file...

 distanceMoved = distanceMoved + totaldistancecovered ;
 theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];

これがお役に立てば幸いです。

于 2012-04-17T03:55:43.357 に答える
0

最初に行うべきことは、ロケーションマネージャから受信した最初の更新のタイムスタンプをチェックして最初の更新を放電することです。通常、最後の既知の位置がキャッシュされます。次に、精度を覚えておいてください。取得する初期値は常に広い範囲にあります。

于 2012-04-17T04:21:58.757 に答える