0

私は、アクティビティ中に iPhone の位置を地図上に表示することを目的としたアプリケーションに取り組んでいます (注釈を追加し、それらの間に線を引きます)。

これを行うには、新しい位置を取得して MapDisplayViewController に通知する Location Manager を使用します。シミュレーターで使用すると、 http://www.youtube.com/watch?v=ESLIYSU_Mqwで確認できるように良好な結果が得られましたが、iPhone では 200 メートルも間違った奇妙な結果が得られました。

また、MKMapView を使用してデバイスの位置を表示します。これらの設定 (次のコード ブロック) で、http://grab.by/mgUUを取得しました。

ユーザーの場所を表示すると、異なる結果が得られましたが、それは正常ですか?

- (void)setupMap {
self.mapView.delegate = self;

[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
[self.mapView setUserInteractionEnabled:NO];

[self.mapView setShowsUserLocation:NO];
[self.mapView setZoomEnabled:NO];
[self.waitingView start];

}

実際のデバイスでのスクリーンショット:

編集:違いは、これら 2 つのケースで使用したものに由来します。デバイスの現在の場所を取得する 2 つの異なる方法が使用されます。

  • アプリがアクティブなときの mapView からのハンドル
  • アプリがバックグラウンドにあるときの Location Manager からのハンドル

両方のロケーション システムを混在させるのは良い考えですか?

このソリューションの CLLocationManager と精度の問題もテストします - 何か経験はありますか? しかし、私は同じ結果を得ました。

ありがとう ;)

ロケーションマネージャーのセットアップ:

- (void)setup {
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;

self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.isUpdatingLocation = NO;
}

通知:バックグラウンドで場所を追加する場合:

- (void)doUpdateWithLocation:(CLLocation *)location {

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    [self beginBackgroundUpdateTask];


    NSLog(@"%s do update in background %@", __PRETTY_FUNCTION__, location);

    if (self.userLocationFound == NO && self.isUpdatingLocation == YES) {
        self.startCoordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);

        self.userLocationFound = YES;
    }
    else if (self.isUpdatingLocation) {
        static int distance;

        ABGPSPosition *position = [[ABGPSPosition alloc] init];
        position.startPoint = MKMapPointForCoordinate(self.startCoordinate);
        position.endPoint = MKMapPointForCoordinate(location.coordinate);

        //INFO: Get the distance between this new point and the previous point.
        CLLocationDistance metersApart = MKMetersBetweenMapPoints(position.startPoint, position.endPoint);
        if (metersApart > MINIMUM_DELTA_METERS) {
            MKMapPoint points[2] = {position.startPoint, position.endPoint};


            distance += metersApart;
            NSLog(@"%s - %d", __PRETTY_FUNCTION__, distance);

            NSInteger count = [self.measurementArray count];
            [self willChange:NSKeyValueChangeInsertion
             valuesAtIndexes:[NSIndexSet indexSetWithIndex:count] forKey: @"measurementArray"];
            [self.measurementArray insertObject:location atIndex:count];
            [self didChange:NSKeyValueChangeInsertion
            valuesAtIndexes:[NSIndexSet indexSetWithIndex:count] forKey: @"measurementArray"];


            self.startCoordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
        }

    }

        [self endBackgroundUpdateTask];
    });
}

MapDisplayViewController は新しい場所を取得します:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{

if ([keyPath isEqualToString:keyPathMeasurementArray]) {
    if ([change[NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeInsertion) {      

        NSIndexSet *insertedIndexSet = change[NSKeyValueChangeIndexesKey];

        [insertedIndexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {

            CLLocation *location = self.locationManager.measurementArray[idx];

            MKUserLocation *userLocation = [[MKUserLocation alloc] init];
            [userLocation setCoordinate:location.coordinate];
            NSLog(@"%s - didUpdateUserLocation", __PRETTY_FUNCTION__);

                [self.locationBackgroundList addObject:userLocation];
                NSLog(@"%s | %@", __PRETTY_FUNCTION__, self.locationBackgroundList);                
        }];
    }
}
else {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}

MapDisplayViewController に Annotation を新しいマップ ビューに追加します。

- (void)handleAddLocations {
NSLog(@"%s | %@", __PRETTY_FUNCTION__, self.locationBackgroundList);

if ([self.locationBackgroundList count] > 0) {
    for (MKUserLocation *backgroundUserLocation in self.locationBackgroundList) {

        {
            LocAnnotation* annotation = [[LocAnnotation alloc] initWithCoordinate:backgroundUserLocation.coordinate];
            NSLog(@"%s %@", __PRETTY_FUNCTION__, [backgroundUserLocation description]);



            [self.mapView addAnnotation:annotation];
        }
        [self mapView:self.mapView didUpdateUserLocation:backgroundUserLocation];
    }

    NSString *message = [NSString stringWithFormat:@"%s | Annotation number: %d", __PRETTY_FUNCTION__, [self.locationBackgroundList count]];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Debug" message:message delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
    [alert show];

    [self.locationBackgroundList removeAllObjects];
    self.locationBackgroundList = [[NSMutableArray alloc] init];
    }
}
4

1 に答える 1