sos の 作業メモ

プログラミングや英会話学習、マイルや旅行、日常生活など。最近はWebFormなASP.NETのお守りがお仕事です。

日々の生活にhappyをプラスする|ハピタス Gポイント

地図を表示する (5.0以降のみ)

iOSでMapKitを使って地図表示を行うのはとても簡単です。5.0以降ならAndroidのMapActivityのように、位置情報を取得して、現在位置のトラッキングも勝手にやってくれるような機能まで入っています。 地図の出し方なんて今更な気もするのですが、iOSでちゃんとした地図アプリを書くのは初めてなので、実装にあたって調べたことをメモしておきます。

5.1.1と 6.0以降で中身が劇的に変化しちゃいましたが、frameworkレベルでは別に大差ありません…いや6.0で経路情報がもらえるんでしたっけ?普通に地図を出す方法は一緒ということで、深く考えないようにしておきます。

余談ですが、 6.0以降専用のGoogle Maps API for iOSも研究してみましたが、Google Maps Android API v2 と同時期にリリースしてきただけあって、かなり良いできです。今のうちに研究だけでもしておいた方が良いかもしれません。

centerCoordinate

表示中の地図の中心座標

typedef struct {
   CLLocationDegrees latitude;
   CLLocationDegrees longitude;
} CLLocationCoordinate2D;

緯度、経度をそれぞれ度で指定する

mapType

地図の種類

  • MKMapTypeStandard - 道路地図
  • MKMapTypeSatellite - 衛星画像
  • MKMapTypeHybrid - 衛星+道路

region / setRegion: animated:

地図の表示範囲。中心と、縦横を度で指定する。

typedef struct {
   CLLocationCoordinate2D center;
   MKCoordinateSpan span;
} MKCoordinateRegion;

typedef struct {
   CLLocationDegrees latitudeDelta;
   CLLocationDegrees longitudeDelta;
} MKCoordinateSpan;

設定したspanが設定されるわけではなく、適切な値に丸められる。どんな値になるのかを予め計算したいときは、

- (MKCoordinateRegion)regionThatFits:(MKCoordinateRegion)region

を使って計算する。

showsUserLocation

地図上にユーザーの現在位置を表示するかどうか。これがYESの間、位置情報の取得が行われ、userLocationに設定される。

userTrackingMode / setUserTrackingMode:animated:

ユーザーの現在位置を追跡するかどうか。

  • MKUserTrackingModeNone - なし
  • MKUserTrackingModeFollow - 現在位置を地図中心にする
  • MKUserTrackingModeFollowWithHeading - 現在位置を地図中心にし、方向にあわせて回転させる

Follow系のモードに設定した際には、ズームレベルが勝手に調整される。また、Followモードはユーザーが画面をある程度ドラッグすると解除される。

userLocation

showUserLocationがYESの時に、ユーザーの現在位置が格納される。MKUserLocationオブジェクト。

delegate

地図表示中のイベントのDelegate。定義しとくとよさげなのは以下の4つ。

- (void)mapViewDidFailLoadingMap:(MKMapView )mapView withError:(NSError )error

ネットワークエラー等で、地図データ読み込みに失敗した時に呼ばれる。

- (void)mapView:(MKMapView )mapView didUpdateUserLocation:(MKUserLocation )userLocation

shorUserLocation=YESの時、位置情報が更新される度に呼ばれる。

- (void)mapView:(MKMapView )mapView didFailToLocateUserWithError:(NSError )error

位置情報の取得が許可されていない等で、測位できなかった時に呼ばれる。

- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated

userTrackingModeが変更された時に呼ばれる。

初期表示位置の調整

userTrackingModeがFollowになっている場合、centerもspanもMap側に主導権を握られているのでたいしたことはできない。Followはしたいが、勝手にズームを変更されたくないという場合には、Noneで現在位置を表示しつつ、Delegateの位置情報更新メソッドでcenterLocationを設定するような処理を追加する必要がある。

ちなみに、私はviewDidLoadでこんな処理を書いています。(CoreLocationに直近の位置情報があればそれを中心として表示)

- (void)viewDidLoad
{
    [super viewDidLoad];

    _mapView.delegate = self;
    _mapView.showsUserLocation = YES;

    MKCoordinateRegion region;
    region.span.latitudeDelta = 0.01;
    region.span.longitudeDelta = 0.01;
    if(_mapView.userLocation){
        CLLocation* userloc = _mapView.userLocation.location;
        if(userloc){
            region.center.latitude = userloc.coordinate.latitude;
            region.center.longitude = userloc.coordinate.longitude;
        }
    }else{
        region.center.latitude = 35;
        region.center.longitude = 135;
    }

    [_mapView setRegion:region animated:NO];
    _mapView.userTrackingMode = MKUserTrackingModeFollow;
}

測位可能かどうかの判定

測位サービスが使用可能かどうかを調査するメソッドは以下

[CLLocationManager locationServicesEnabled]

ただし、これは位置情報サービスが onになっているかどうかを返すだけで、アプリに対して許可されているかどうかはわからない。そちらを知るためには、実際に位置情報を取得してみて、Delegateでエラーが返ってくるかどうかを確認するしかない。

とりあえずここまで

Annotation(画面上に置くPinと注釈)とOverlayはまた別の機会にでも。