web-dev-qa-db-ja.com

CLLocationManagerなしでMKMapViewをユーザーの現在位置にズームするにはどうすればよいですか?

MKMapViewには、[ユーザーの現在位置を表示]というオプションがあり、mapのユーザーの位置を自動的に表示します。

この場所が見つかった場合(および変更された場合)、この場所に移動してズームしたいと思います。

問題は、mapでユーザーの場所が更新されたときに呼び出されるメソッドが存在しないように見えるため、zoom/scroll

MKMapViewがユーザーの場所を取得(または更新)したときに通知される方法があるので、移動したりズームしたりできますか?独自のCLLocationManagerを使用すると、更新がマップ上のユーザーマーカーの更新に対応しないため、青いピンが表示される数秒前にマップが移動してズームすると愚かに見えます。

これは基本的な機能のように感じますが、解決策を探すのに何週間も費やしました。

70
Danny Tuppeny

MKMapViewuserLocation.locationプロパティのKVO通知に登録する必要があります。

これを行うには、ViewControllerのviewDidLoad:またはマップビューが初期化される場所のどこかにこのコードを配置します。

[self.mapView.userLocation addObserver:self  
        forKeyPath:@"location"  
           options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)  
           context:NULL];

次に、このメソッドを実装してKVO通知を受信します

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

    if ([self.mapView showsUserLocation]) {  
        [self moveOrZoomOrAnythingElse];
        // and of course you can use here old and new location values
    }
}

このコードは私にとってはうまく機能します。
ところで、selfはこのコンテキストでの私のViewControllerです。

106
ddnv

これはddnvとダスティンの答えを組み合わせたもので、私にとってはうまくいきました。

mapViewはMKMapView * mapViewの名前です。

ViewDidLoadでこの行を追加します。ロードにさらに行がある可能性があることに注意してください。これは単純化されています。

- (void) viewDidLoad
{
    [self.mapView.userLocation addObserver:self 
                                forKeyPath:@"location" 
                                   options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) 
                                   context:nil];
}

次に、マップを現在の場所に移動する実際のリストメソッドを作成します。

// Listen to change in the userLocation
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{       
    MKCoordinateRegion region;
    region.center = self.mapView.userLocation.coordinate;  

    MKCoordinateSpan span; 
    span.latitudeDelta  = 1; // Change these values to change the zoom
    span.longitudeDelta = 1; 
    region.span = span;

    [self.mapView setRegion:region animated:YES];
}

適切に割り当てを解除し、オブザーバーの登録を解除することを忘れないでください。

- (void)dealloc 
{
    [self.mapView.userLocation removeObserver:self forKeyPath:@"location"];
    [self.mapView removeFromSuperview]; // release crashes app
    self.mapView = nil;
    [super dealloc];
}
52
MrHus

IOS 5.0以降、AppleはMKMapViewに新しいメソッドを追加しました。このメソッドは、まさにあなたが望むことなどを行います。

以下をご覧ください: https://developer.Apple.com/documentation/mapkit/mkmapview

- (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;
45
thijsai

MKMapViewプロトコルを実装することにより、MKMapViewDelegateがマップ上のユーザーの場所を更新するタイミングを監視できます。実装するだけです:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation      {
    CLLocationAccuracy accuracy = userLocation.location.horizontalAccuracy;
    if (accuracy ......) {
    } 
}

このコールバックは、マップに表示されるものと完全に同期する必要があります。

13
yonel

これを試して:

[mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
6

問題ありません... MKMapViewを持つUIViewControllerサブクラスのviewDidLoadメソッド内に、これを追加します(MKMapViewの名前がmapであると仮定):

CLLocation *location = [[[CLLocation alloc] initWithLatitude:map.centerCoordinate.latitude longitude:map.centerCoordinate.longitude] autorelease]; //Get your location and create a CLLocation
MKCoordinateRegion region; //create a region.  No this is not a pointer
region.center = location.coordinate;  // set the region center to your current location
MKCoordinateSpan span; // create a range of your view
span.latitudeDelta = BASE_RADIUS / 3;  // span dimensions.  I have BASE_RADIUS defined as 0.0144927536 which is equivalent to 1 mile
span.longitudeDelta = BASE_RADIUS / 3;  // span dimensions
region.span = span; // Set the region's span to the new span.
[map setRegion:region animated:YES]; // to set the map to the newly created region
1