Help us understand the problem. What is going on with this article?

MKMapView のユーザートラッキングモードを標準マップアプリと同等に実装する

More than 5 years have passed since last update.

iOS 8 がそろそろ出る、というタイミングでずいぶんレガシーな話ですいません。iOS 5 の頃からある MKUserTrackingMode をどう扱えば標準マップアプリと同等になるか、の実装手順メモです。ここはアプリによって違うことはあまりなく、だいたいワンパターンだと思うので。

ユーザートラッキングモードとは

ユーザートラッキングモードというのは、標準マップアプリにも Google Maps アプリにもついている、

trackingmode.jpg

こういうボタンで順番に切り替わるもので、MKMapView では以下の3種が定義されてます。

  • MKUserTrackingModeNone ・・・ユーザーの現在位置に応じてマップを更新しない
  • MKUserTrackingModeFollow ・・・ユーザーの現在位置に応じてマップを更新する
  • MKUserTrackingModeFollowWithHeading ・・・ユーザーの現在位置と 進行方向 に応じてマップを更新する

ちなみに上の写真は自分の進行方向に応じて地図の向きが変わる MKUserTrackingModeFollowWithHeading です。

ボタン画像変更メソッド

モードが切り替わったときにボタンの画像を切り替えるメソッドを用意します。

- (void)updateUserTrackingModeBtn:(MKUserTrackingMode)mode {

    NSString *filename = nil;

    switch (mode) {
        case MKUserTrackingModeNone:
        default:
            filename = @"tracking_no";
            break;
        case MKUserTrackingModeFollow:
            filename = @"tracking_follow";
            break;
        case MKUserTrackingModeFollowWithHeading:
            filename = @"tracking_heading";
            break;
    }

    [self.userTrackingModeBtn setImage:[UIImage imageNamed:filename]
                              forState:UIControlStateNormal];
}

ボタンのアクション

モード切り替えボタンのアクションとして、MKMapView の userTrackingMode プロパティを順番に変更し、それに応じてボタンの画像を変更するメソッドを用意します。

- (IBAction)userTrackingModeBtnTapped:(id)sender {

    MKUserTrackingMode mode;

    switch (self.mapView.userTrackingMode) {
        case MKUserTrackingModeNone:
        default:
            mode = MKUserTrackingModeFollow;
            break;
        case MKUserTrackingModeFollow:
            mode = MKUserTrackingModeFollowWithHeading;
            break;
        case MKUserTrackingModeFollowWithHeading:
            mode = MKUserTrackingModeNone;
            break;
    }

    [self updateUserTrackingModeBtn:mode];
    [self.mapView setUserTrackingMode:mode animated:YES];
}

初期設定

viewDidLoad あたりで、初期値にしておきます。

[self.mapView setUserTrackingMode:MKUserTrackingModeNone animated:YES];
[self updateUserTrackingModeBtn:MKUserTrackingModeNone];

ユーザー操作による変更

標準マップアプリを見てると、少しマップを動かすと、そのとき MKUserTrackingMode が MKUserTrackingModeFollow であっても MKUserTrackingModeFollowWithHeading であっても、MKUserTrackingModeNone強制的に戻されることがわかります。

これを実現するのに、最初は自分で mapView:regionDidChangeAnimated: でマップ移動をフックしてモード切り替えするのかなーと思ったのですがそうではなく、 MKMapView内部で勝手に切り替えてくれている ようです。

というわけで、 mapView:didChangeUserTrackingMode:animated: でモード切り替えをフックし、ボタン画像をそれに適したものに変更すればOK。

- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
    [self updateUserTrackingModeBtn:mode];
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした