MKMapView
には、[ユーザーの現在位置を表示]というオプションがあり、map
のユーザーの位置を自動的に表示します。
この場所が見つかった場合(および変更された場合)、この場所に移動してズームしたいと思います。
問題は、map
でユーザーの場所が更新されたときに呼び出されるメソッドが存在しないように見えるため、zoom/scroll
。
MKMapView
がユーザーの場所を取得(または更新)したときに通知される方法があるので、移動したりズームしたりできますか?独自のCLLocationManager
を使用すると、更新がマップ上のユーザーマーカーの更新に対応しないため、青いピンが表示される数秒前にマップが移動してズームすると愚かに見えます。
これは基本的な機能のように感じますが、解決策を探すのに何週間も費やしました。
MKMapView
のuserLocation.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です。
これは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];
}
IOS 5.0以降、AppleはMKMapViewに新しいメソッドを追加しました。このメソッドは、まさにあなたが望むことなどを行います。
以下をご覧ください: https://developer.Apple.com/documentation/mapkit/mkmapview
- (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;
MKMapView
プロトコルを実装することにより、MKMapViewDelegate
がマップ上のユーザーの場所を更新するタイミングを監視できます。実装するだけです:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
CLLocationAccuracy accuracy = userLocation.location.horizontalAccuracy;
if (accuracy ......) {
}
}
このコールバックは、マップに表示されるものと完全に同期する必要があります。
これを試して:
[mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
問題ありません... 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