位置情報とマップ プログラミングガイド

位置情報とマップ プログラミングガイド
位置情報とマップ
プログラミングガイド
目次
位置情報サービスと地図について 7
はじめに 8
アプリケーションに地理上のコンテキストを提供する位置情報サービス 8
iBeacons送信機により、ユーザの位置情報に関する体験を拡張 8
ユーザの現在の向きを示すヘディング情報 9
ナビゲーションおよび地理的に関連のあるコンテンツの表示をサポートするマップ 9
ユーザに道順を示す経路制御アプリケーション 9
ローカル検索 10
この文書の使い方 10
関連項目 10
ユーザの位置の取得 11
位置情報サービスが利用できる旨の要求(iOSアプリケーション) 11
ユーザの現在位置の取得 12
位置情報サービスの利用可否の確認 12
標準位置情報サービスの開始 13
大幅変更位置情報サービスの開始 14
サービスからの位置データの受信 16
位置情報サービスを起動するべき時点の判断 17
バックグラウンドでの位置情報イベントの取得(iOSのみ) 17
標準位置情報サービスのバックグラウンドでの使用 18
バックグラウンド状態である間の、位置情報の更新延期 20
バッテリー電力節約のためのヒント 22
領域観測とiBeacon 24
領域観測の利用可否の確認 24
地理的領域の観測 26
観測する地理的領域の定義 26
地理的領域の境界線横断イベントの処理 27
ビーコン領域の観測 28
観測するビーコン領域の定義 28
ビーコン領域の境界線横断イベントの処理 29
iOSデバイスをiBeaconとして利用 32
ビーコン領域の作成とアドバタイズ 32
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
2
目次
iOSアプリケーションの領域観測サポートのテスト 35
デバイスのヘディングとコースの取得 36
方向関連のイベントのための要件の追加 36
方角(ヘディング)関連イベントの取得 37
ユーザーの移動中にコース情報を取得する 39
位置データのジオコーディング 40
Geocoderオブジェクトについて 40
CLGeocoderでプレースマーク情報を取得 41
プレース名を座標に変換する 42
地図の表示 44
地図ジオメトリの理解 44
地図の座標系 45
座標系の変換 46
ユーザインターフェイスへのMap Viewの追加 47
地図のプロパティの設定 48
地図の可視部分の設定 48
3D地図の表示 49
地図コンテンツの拡大縮小とパン 51
地図上でのユーザの現在位置の表示 52
地図のスナップショット作成 52
デリゲートを使ってユーザの操作に応答 55
「マップ(Maps)」アプリケーションの起動 55
地図の注釈 56
地図への注釈の追加 56
注釈を地図に追加する手順 58
カスタム注釈オブジェクトの定義 59
標準注釈ビューの使用 61
カスタム注釈ビューの定義 61
デリゲートオブジェクトからの注釈ビューの作成 63
吹き出しの作成 64
複数の注釈オブジェクトの表示 68
注釈ビューをドラッグ可能として登録する 68
地図へのオーバーレイの表示 69
地図にオーバーレイを追加する手順 71
標準のオーバーレイオブジェクトとビューの使用 72
タイル化オーバーレイの取り扱い 74
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
3
目次
カスタムオーバーレイオブジェクトの定義 74
カスタムオーバーレイレンダラの定義 75
デリゲートオブジェクトからのオーバーレイレンダラの作成 78
複数のオーバーレイオブジェクトの表示 79
オーバーレイを注釈として使用 79
道順の提示 81
「マップ(Maps)」アプリケーションに道順を表示するよう要求する 81
経路制御アプリケーションとして登録する(iOS のみ) 82
道順の要求をアプリケーションで受け入れるための設定 83
道順でサポートされる対応地域カバレージの宣言 84
URLによる道順要求の取り扱い 88
汎用の道順情報の取得 89
検索機能の組み込み 92
書類の改訂履歴 94
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
4
図、表、リスト
ユーザの位置の取得 11
リスト 1-1
リスト 1-2
リスト 1-3
リスト 1-4
標準位置情報サービスの開始 14
大幅変更位置情報サービスの開始 15
受信した位置情報イベントの処理 16
位置情報の遅延更新 20
領域観測とiBeacon 24
リスト 2-1
リスト 2-2
リスト 2-3
Map Kitオーバーレイに基づいた地理的領域の作成と登録 26
ビーコン領域の作成と登録 29
ビーコンとデバイスの相対距離を判定するコード例 31
デバイスのヘディングとコースの取得 36
リスト 3-1
リスト 3-2
ヘディングイベントの送信を開始する 37
ヘディングイベントを処理する 38
位置データのジオコーディング 40
リスト 4-1
CLGeocoderを用いた位置のジオコーディング 41
地図の表示 44
図 5-1
表 5-1
リスト 5-1
リスト 5-2
リスト 5-3
球状データから平面へのマッピング 45
地図座標系変換ルーチン 46
3D地図の生成 50
地図のアーカイブ保存と復元 51
地図の印刷に用いるスナップショットの生成 54
地図の注釈 56
図 6-1
図 6-2
図 6-3
図 6-4
リスト 6-1
リスト 6-2
リスト 6-3
リスト 6-4
地図での注釈の表示 57
標準の吹き出しにカスタム画像および詳細開示ボタンを表示している様子 65
地図へのオーバーレイの表示 70
カスタムオーバーレイレンダラを使用した描画 78
シンプルな注釈オブジェクトの作成 59
MyCustomAnnotationクラスの実装 60
カスタム画像を指定した標準注釈ビューの作成 61
カスタム注釈ビューの初期化 62
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
5
図、表、リスト
リスト 6-5
リスト 6-6
リスト 6-7
リスト 6-8
リスト 6-9
リスト 6-10
リスト 6-11
注釈ビューの作成 63
標準の吹き出しのカスタマイズ 65
カスタムの吹き出し内でのヒットに応答 67
カスタムの吹き出しビューを追加/削除 67
ポリゴンのオーバーレイオブジェクトの作成 72
図形描画のためのポリゴンレンダラの作成 73
カスタムオーバーレイでのグラデーションの描画 76
道順の提示 81
図 7-1
表 7-1
リスト 7-1
リスト 7-2
リスト 7-3
リスト 7-4
リスト 7-5
スキームエディタでGeoJSONファイルを選択している様子 87
道順要求ドキュメントタイプのキーと値 83
「マップ(Maps)」アプリケーションによる位置情報の表示 82
GeoJSONファイルの例 85
道順要求URLの処理 88
道順の要求 90
代替経路の表示 91
検索機能の組み込み 92
リスト 8-1
ユーザ入力に合致する場所を検索するコード例 93
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
6
位置情報サービスと地図について
アプリケーションに位置ベースの情報を取り入れることで、ユーザが周囲の世界とのつながりを保て
る手段を提供できます。位置ベースの情報を実用目的で利用するのか(たとえばナビゲーション)、
娯楽目的で利用するのかを問わず、こうした情報によりユーザ体験を全体的に向上させることができ
ます。
位置ベースの情報は、位置情報サービスと地図の2つで構成されます。位置情報サービスはCore Location
フレームワークによって提供されます。このフレームワークは、ユーザの位置と方向(デバイスが指
す向き)に関する情報を得るためのObjective-Cのインターフェイスを定義しています。地図はMap Kit
フレームワークによって提供されます。このフレームワークは、「マップ(Maps)」アプリケーション
と同じように、地図の表示と注釈をサポートします(Map Kitフレームワークの機能を使用するには、
Xcodeプロジェクトで「Maps」技術を有効にする必要があります)。位置情報サービスや地図は、iOS
とOS Xのどちらでも利用できます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
7
位置情報サービスと地図について
はじめに
はじめに
地理データをアプリケーションに組み込むことにより、ユーザを周囲の環境に向けさせたり、周囲の
人々とのつながりを保てるようにしたりできます。
位置情報サービスや地図は、iOSとOS Xのどちらでも利用できるので、この技術を組み込んだアプリ
ケーションは、どちらのプラットフォームでもよく似たコードになります。違いがあるのは、ユーザ
インターフェイス周辺のコード(たとえばiOSならばUIView、OS XならばNSViewを用いるなど)と、
iOSでのみ実行可能な若干の機能(ヘディングサービスなど)だけです。
アプリケーションに地理上のコンテキストを提供する位置情報サービス
ユーザの地理的な位置を知ることで、提供する情報の質を上げることができ、それがアプリケーショ
ンの中核をなすこともあります。ナビゲーション機能を備えたアプリケーションは、位置情報サービ
スを利用してユーザの位置を観測し、更新情報を生成します。あるいは、近隣ユーザどうしの社会的
なつながりを実現するために、位置情報を利用するアプリケーションもあります。
関連する章: “ユーザの位置の取得” (11 ページ)、“領域観測とiBeacon” (24 ページ)、
“位置データのジオコーディング” (40 ページ)
iBeacons送信機により、ユーザの位置情報に関する体験を拡張
iBeacons送信機は、Bluetooth Low-Energyワイヤレステクノロジーを使って特定の識別情報をアドバタ
イズするビーコンを、作成して監視する方法を提供しています。同じUUID(Universally Unique Identifier)
をアドバタイズするBluetooth Low-Energyビーコンは、アプリケーションがCore Location領域観測サ
ポートを使用して観測可能なビーコン領域を形成します。同じUUIDのビーコンも、アドバタイズする
追加情報によって区別できます。ビーコンがユーザのデバイスの範囲内にある場合は、アプリケー
ションはビーコンからの相対距離を監視することもできます。
ビーコンによってアドバタイズされる情報は、特定の位置におけるユーザの体験を拡張するために使
用できます。たとえば博物館用アプリケーションでは、館内の重要な展示物の近くに配置されている
ビーコンを監視することができます。ユーザが特定の展示物に近づくと、アプリケーションはビーコ
ンとの相対距離を使用して、他の展示物ではなく、この展示物についての追加情報を提供するきっか
けにすることができます。
ビーコンはBluetooth Low-Energyテクノロジーを使用して情報をアドバタイズするため、Bluetooth
Low-Energyによるデータ共有をサポートする任意のiOSデバイスをビーコンデバイスにすることがで
きます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
8
位置情報サービスと地図について
はじめに
関連する章: “領域観測とiBeacon” (24 ページ)
ユーザの現在の向きを示すヘディング情報
ヘディングサービスは基本的な位置情報サービスを補うもので、デバイスが向いている方向に関す
る、より正確な情報を提供します。このテクノロジーの使用法としてすぐに思いつくのはコンパスで
すが、AR(拡張現実)、ゲーム、および道案内アプリケーションをサポートする目的にも使用できま
す。磁気センサー(正確なヘディング情報を得るためのハードウェア)のないデバイス上でも、ユー
ザの進路と速度に関する情報をアプリケーションで利用できます。
関連する章: “デバイスのヘディングとコースの取得” (36 ページ)
ナビゲーションおよび地理的に関連のあるコンテンツの表示をサポートす
るマップ
地図を使って、地理データを分かりやすく視覚化できます。たとえば、ある地域の衛星データを表示
する、ある角度から俯瞰した様子を見せる、建物を立体的に表して地域全体を3D表示する、といった
ことが可能です。Map Kitフレームワークの標準ビューをアプリケーションに組み込んで、地理上の特
定の地点に結び付けられた情報を表示できます。さらに、カスタム情報を地図の前面に配置し、それ
を地図のほかの内容とともにスクロールさせ、表示内容のスナップショットを取得して印刷に用いる
手段を提供します。
関連する章: “地図の表示” (44 ページ)、“地図の注釈” (56 ページ)
ユーザに道順を示す経路制御アプリケーション
経路制御アプリケーションは、「マップ(Maps)」アプリケーションから座標を受け取って、この座標
を使用してある地点から別の地点への道順をユーザに提供します。道案内機能を備えたアプリケー
ションは、最小限の労力を割くだけで、経路制御アプリケーションであると宣言できます。ドライブ
時および徒歩時の道順に加えて、経路制御アプリケーションでは、タクシや飛行機、さまざまな公共
交通機関など、各種の交通手段によるモードに対応できます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
9
位置情報サービスと地図について
この文書の使い方
関連する章: “道順の提示” (81 ページ)
ローカル検索
名称、住所、建物の種類などを記述して、該当する場所を見つけたい、という需要も少なくありませ
ん。Map Kitのローカル検索APIを利用すれば、こういった情報をユーザに入力させ、検索結果を地図
上に表示することができます。
関連する章: “検索機能の組み込み” (92 ページ)
この文書の使い方
個々のテクノロジーを使用するにあたり、この文書全体を読み通す必要はありません。Core Location
フレームワークおよびMap Kitフレームワークによって提供されるサービスは、ほかのサービスに依存
せずに使用できます。各章の冒頭では、各テクノロジーを理解するために必要な用語と情報を紹介
し、テクノロジーの使用方法に関するサンプルと、タスク関連の手順を取り上げています。“地図の
注釈” (56 ページ)の章だけは、“地図の表示” (44 ページ)の章に掲載されている情報を前提に書
かれています。
関連項目
Core Locationフレームワークのクラスの詳細については、『Core Location Framework Reference 』を参
照してください。
Map Kitフレームワークのクラスの情報については、『Map Kit Framework Reference 』を参照してくだ
さい。
プロジェクトでMapsサービスを有効にする方法については、『AppDistributionGuide 』の「Configuring
Maps」を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
10
ユーザの位置の取得
アプリケーションは、ソーシャルネットワーキングサービスから道案内サービスまで、さまざまな目
的で位置情報を利用します。こうしたアプリケーションは、Core Locationフレームワークのクラスを
介して位置データを取得します。このフレームワークは、次に示すように、デバイスの現在位置の取
得と観測が可能なサービスを提供しています。
●
●
●
大幅変更位置情報サービス。このサービスは、少ない電力消費で現在位置を取得し、大幅な変更
が生じていればその旨を通知します。
標準位置情報サービス。現在位置および経路の変化を取得する、詳細な設定が可能な方法を提供
します。
領域観測は、定義済みの地理的領域およびBluetooth Low-Energyビーコン領域に対する境界線の横
断を監視します(ビーコンによる領域観測はiOSでのみ利用可)。
Core Locationフレームワークの機能を使用するには、Xcodeプロジェクトでアプリケーションを
CoreLocation.frameworkにリンクする必要があります。このフレームワークのクラスとヘッダにア
クセスするには、関連するソースファイルの先頭に#import <CoreLocation/CoreLocation.h>ス
テートメントを追加します。
Core Locationフレームワークのクラスの全般的な情報については、『CoreLocationFrameworkReference 』
を参照してください。
位置情報サービスが利用できる旨の要求(iOSアプリケーショ
ン)
iOSアプリケーションを正しく機能させるために位置情報サービスが必要な場合は、アプリケーショ
ンのInfo.plistファイルにUIRequiredDeviceCapabilitiesキーを追加する必要があります。App
Storeは、このキーの情報を使用して、リストに含まれている機能のないデバイスへのアプリケーショ
ンのダウンロードを防ぎます。
UIRequiredDeviceCapabilitiesの値は、アプリケーションが必要とする機能を示す文字列の配列
です。位置情報サービスに関連する文字列は2つあります。
●
一般的な位置情報サービスを必要とする場合は、文字列location-servicesを指定します。
●
GPSハードウェアでしか得られない測地精度を必要とする場合は、文字列gpsを指定します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
11
ユーザの位置の取得
ユーザの現在位置の取得
Important: iOSアプリケーションで位置情報サービスを利用するけれども、位置情報がなくても正
常に動作する場合は、対応する文字列をUIRequiredDeviceCapabilitiesキーに指定しないでく
ださい。
UIRequiredDeviceCapabilitiesキーの詳細については、『Information Property List Key Reference 』
を参照してください。
ユーザの現在位置の取得
Core Locationフレームワークを使用すると、デバイスの現在位置を検出してその情報をアプリケーショ
ンで使用できます。フレームワークは、デバイスの位置をアプリケーションのコードに報告し、サー
ビスをどのように設定したかに応じて、新しいデータやより精度の高いデータを受信すると定期的に
更新情報も提供します。
ユーザの現在位置を取得する手段として、次の2つのサービスがあります。
●
●
標準位置情報サービス。きめ細かな設定が可能な汎用のソリューションで、所定の精度で位置
データを取得し、その変化を追跡することができます。
大幅変更位置情報サービス。デバイスの位置が大幅に(たとえば500メートル以上)変化したと
きにのみ、更新情報を送ります。
位置データの収集には、集中的に電力を消費します。ほとんどのアプリケーションの場合、最初の位
置を検出した後は、定期的に更新情報を取得すれば十分です。アプリケーションによって位置情報
データの重要性は異なるので、電池を無駄に消費しないよう、適切な位置情報サービスを選択してく
ださい。以下に例を挙げます。
●
iOSアプリケーションが、バックグラウンド状態であっても位置情報を監視し続けなければならな
いのであれば、標準位置情報サービスを使い、UIBackgroundModesキーにlocationという値を
指定して、位置の更新情報を受け取れるようにしてください(この場合、電池の消耗を抑えるた
め、位置情報マネージャのpausesLocationUpdatesAutomaticallyプロパティをYESとすること
も必要)。このような位置更新情報を要するものとして、フィットネスや道案内のアプリケー
ションが考えられます。
●
GPSレベルの精度も、継続的に追跡することも必要なければ、大幅変更位置情報サービスを利用
してください。継続的には追跡せず、大幅に位置が変わった場合のみ、デバイスを「起こし」て
アプリケーションを起動するようになっているので、電池の消耗を抑制できます。
位置情報サービスの利用可否の確認
位置情報サービスが使えない状況がいくつかあります。以下に例を挙げます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
12
ユーザの位置の取得
ユーザの現在位置の取得
●
ユーザが「設定(Settings)」アプリケーションやシステム環境設定で位置情報サービスを無効にし
ている。
●
ユーザが特定のアプリケーションに対して位置情報サービスを拒否している。
●
デバイスが機内モードになっていて、必要なハードウェアの電源を入れられない。
このような理由から、標準または大幅変更位置情報サービスを開始する前に、必ずCLLocationManager
のlocationServicesEnabledクラスメソッドを呼び出すべきです。NOが返された場合に位置情報サー
ビスを開始しようとすると、システムはユーザに位置情報サービスを再度有効にするべきかどうか確
認を求めてきます。おそらくユーザは、意図的に位置情報サービスを無効にしているので、この確認
はわずらわしいと思われるかも知れません。
標準位置情報サービスの開始
標準位置情報サービスは、すべてのデバイス上で、iOSとOS Xのどちらでも利用できるため、ユーザ
の現在位置を取得する最も一般的な方法です。このサービスを利用する前に、位置データの測地精度
と、新しい位置を報告するまでに必要な移動距離を指定します。標準位置情報サービスは開始時に、
指定されたパラメータに応じてどのハードウェアを有効にするかを決めて、その後アプリケーション
へ位置情報イベントを報告します。このサービスは、これらのパラメータが考慮されるため、位置情
報イベントの送信に関して、よりきめの細かい制御が必要になるアプリケーションに最適です。標準
位置情報サービスの測地精度は、道案内アプリケーション、または測地精度の高い位置情報データも
しくはストリームの定期的な更新が必要なアプリケーションで必要です。このサービスは通常、位置
情報追跡ハードウェアを長時間にわたって有効にする必要があり、電力の使用量が高くなることがあ
ります。
標準位置情報サービスを使用するには、CLLocationManagerクラスのインスタンスを作成し、その
desiredAccuracyプロパティおよびdistanceFilterプロパティを設定します。位置情報通知の受け
取りを開始するには、そのオブジェクトにデリゲートを割り当て、startUpdatingLocationメソッ
ドを呼び出します。位置データが利用可能になると、この位置情報マネージャは割り当てられている
デリゲートオブジェクトに通知をします。位置情報の更新がすでに送信されていれば、次のイベント
の送信を待たずに、最新の位置データをCLLocationManagerオブジェクトから直接取得することも
できます。位置情報更新の送信を停止するには、位置情報マネージャオブジェクトの
stopUpdatingLocationメソッドを呼び出します。
リスト 1-1に、使用する位置情報マネージャを設定するメソッドの例を示します。このメソッド例は、
位置情報マネージャオブジェクトを後での使用に備えてメンバー変数にキャッシュするクラスの一部
です(このクラスはまた、CLLocationManagerDelegateプロトコルにも準拠しているため、位置情
報マネージャのデリゲートとしても機能します)。アプリケーションが厳密な位置データを必要とし
ないため、ユーザのおおよその地域を報告し、0.5km以上移動したときにのみ通知するよう、位置情
報サービスを設定しています。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
13
ユーザの位置の取得
ユーザの現在位置の取得
リスト 1-1
標準位置情報サービスの開始
- (void)startStandardUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
locationManager.distanceFilter = 500; // meters
[locationManager startUpdatingLocation];
}
このサービスから位置情報の更新を受信するコードは、“サービスからの位置データの受信” (16 ペー
ジ)に示します。
大幅変更位置情報サービスの開始
大幅変更位置情報サービスは、標準位置情報サービスに代わるもので、消費電力を抑えつつ、多くの
アプリケーションにとって十分な精度のデータを提供します。Wi-Fiを利用してユーザの位置を特定
し、その位置の変更を報告します。これによりシステムは、電力使用量をより積極的に管理すること
ができます。さらに、新しい位置データを配送するために、現在一時停止中または実行していないiOS
アプリケーションを「起こす」ことも可能です。
大幅変更位置情報サービスを使用するには、リスト 1-2に示すように、CLLocationManagerクラスの
インスタンスを作成し、デリゲートを割り当て、startMonitoringSignificantLocationChanges
メソッドを呼び出します。位置データが利用可能になると、この位置情報マネージャは割り当てられ
ているデリゲートオブジェクトに通知をします。位置情報の更新がすでに送信されていれば、次のイ
ベントの送信を待たずに、最新の位置データをCLLocationManagerオブジェクトから直接取得する
こともできます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
14
ユーザの位置の取得
ユーザの現在位置の取得
リスト 1-2
大幅変更位置情報サービスの開始
- (void)startSignificantChangeUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startMonitoringSignificantLocationChanges];
}
“サービスからの位置データの受信” (16 ページ)で説明しているように、位置データは標準位置情
報サービスと同様にデリゲートオブジェクトに送信されます。大幅変更位置情報サービスを停止する
には、stopMonitoringSignificantLocationChangesメソッドを呼び出します。
大幅変更位置情報サービスを実行したままにしてアプリケーションが一時停止または終了させられた
場合、新しい位置データが到着したときに、サービスは自動的にアプリケーションを作動させます。
作動させられたアプリケーションはバックグラウンドに回され、手動で位置情報サービスを再起動
し、位置データを処理するための短い時間(約10秒)が与えられます(位置情報サービスをバックグ
ラウンドで再起動しなければ、保留になっていた更新データは配送されません。“位置情報サービス
を起動するべき時点の判断” (17 ページ)を参照)。アプリケーションはバックグラウンドにあるた
め、行う処理を最小限に抑え、割り当てられた時間が経過するまで復帰しない可能性のあるタスク
(ネットワークへの問い合わせなど)は避けます。さもなければアプリケーションは強制終了させら
れます。iOSアプリケーションの位置情報データの処理にさらに長い時間がかかる場合は、
UIApplicationクラスのbeginBackgroundTaskWithName:expirationHandler:メソッドを使用して
より多くのバックグラウンド時間を要求できます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
15
ユーザの位置の取得
ユーザの現在位置の取得
注意: ユーザが「Background App Refresh」設定を、すべてのアプリケーションに対してグ
ルーバルに、または特定のアプリケーションに対してのみ無効にしている場合、大幅変更位
置情報サービスはアプリケーションを再起動しません。さらに、「Background App Refresh」
がオフである間は、フォアグラウンド状態であっても、大幅変更や領域観測に関するイベン
トを受け取ることはありません。
サービスからの位置データの受信
位置情報イベントを受信する方法は、標準位置情報サービスでも大幅変更位置情報サービスでも同じ
です。OS X v10.9およびiOS 6以降では、イベントが利用できるようになると、位置情報マネージャに
よってイベントがデリゲートのlocationManager:didUpdateLocations:メソッドに報告されます
(従来の版では、位置情報マネージャはイベントを
locationManager:didUpdateToLocation:fromLocation:メソッドに報告するようになっていまし
た)。イベントの取得時にエラーが発生すると、位置情報マネージャはデリゲートの
locationManager:didFailWithError:メソッドを代わりに呼び出します。
リスト 1-3に、位置情報イベントを受信するデリゲートメソッドを示します。位置情報マネージャオ
ブジェクトは、キャッシュされているイベントを返すことがあるため、受け取った位置情報イベント
のタイムスタンプを確認することを推奨します(大まかな位置を取得するまで数秒を要する場合があ
ります。したがって、古いデータは、最後に取得した位置を表す手段としてのみ役立ちます)。この
例に示すメソッドは、この時間内のイベントであれば十分に有効であるという想定のもと、15秒以上
が経過しているイベントをすべて破棄します。道案内アプリケーションを実装している場合は、この
しきい値を下げる必要があるかもしれません。
リスト 1-3
受信した位置情報イベントの処理
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power.
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// If the event is recent, do something with it.
NSLog(@"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
16
ユーザの位置の取得
バックグラウンドでの位置情報イベントの取得(iOSのみ)
}
}
位置情報オブジェクトのタイムスタンプのほか、イベントを受け取るかどうかを判断するために、オ
ブジェクトから報告された精度を使用することもできます。位置情報サービスは、より正確なデータ
を受け取ると、その精度の向上を反映した精度値を持つ追加イベントを返します。精度の低いイベン
トを破棄するということは、アプリケーションが、効果的に使用できないイベントに浪費する時間を
減らせるということです。
位置情報サービスを起動するべき時点の判断
位置情報サービスを利用するアプリケーションであっても、実際に必要になるまでは、サービスを起
動しないでください。いくつか例外はありますが、アプリケーションの起動後直ちに、あるいは位置
情報サービスを利用するべき状況になる前に、このサービスを起動してはなりません。位置データを
何のために使うのだろう、という疑念をユーザーに抱かせる恐れがあるからです。アプリケーション
が位置情報サービスを起動すれば、システムは実行してよいか確認するプロンプトを出すので、ユー
ザはその旨を認識することになります。そこで、本当にこのサービスを要する作業が始まってから起
動するようにすれば、適切な使い方になっている、という信頼感を与えることができるでしょう。さ
らに信頼感を得るため、Info.plistファイルのNSLocationUsageDescriptionキーに、位置情報デー
タの用途を説明する文字列を設定するのも効果的です。
領域を観測し、あるいは大幅変更位置情報サービスを利用する場合、アプリケーションの起動と同時
に位置情報サービスも起動しなければならないこともあります。アプリケーション自身はいったん停
止しておき、位置情報イベントが新たに届いた時点で再起動する、という方式も考えらるでしょう。
もっとも、その時点で自動的に位置情報サービスが起動されるわけではありません。位置の更新に
伴ってアプリケーションが再起動されるとき、application:willFinishLaunchingWithOptions:
メソッドまたはapplication:didFinishLaunchingWithOptions:メソッドに渡される起動オプショ
ンの辞書には、UIApplicationLaunchOptionsLocationKeyキーがあります。これは、新しい位置情
報データの配送を待っている状態であることを表します。このデータを取得するためには、
CLLocationManagerオブジェクトを生成し、位置情報サービス(前回のアプリケーション停止時ま
で動作していたもの)を再起動しなければなりません。サービスが再起動されると、位置情報マネー
ジャは保留状態になっていた位置更新情報をすべて、デリゲートに配送します。
バックグラウンドでの位置情報イベントの取得(iOSのみ)
iOSでは、一時停止状態、あるいは既に動作していないアプリケーションに対しても、位置情報イベ
ントを配送できるようになっています。バックグラウンドで位置情報イベントを配送する仕組みは、
位置情報なしには機能を果たさないアプリケーションを想定したものです。したがって、バックグラ
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
17
ユーザの位置の取得
バックグラウンドでの位置情報イベントの取得(iOSのみ)
ウンドでイベントを受信するよう設定するのは、ユーザにとって実益がある場合に限定してくださ
い。たとえば道案内アプリケーションは、ユーザの位置を常に追跡し、次の曲がり角に達する時点で
通知する必要があります。領域観測など別の手段で実装できるならば、その方がよいでしょう。
バックグラウンドで位置情報イベントを取得する方法はいくつかあり、消費電力や精度の観点から見
ると、それぞれ一長一短があります。可能であれば大幅変更位置情報サービス(“大幅変更位置情報
サービスの開始” (14 ページ)を参照)を優先的に使ってください。Wi-Fiでユーザの位置を判断する
方式であり、消費電力を抑制できます。しかし精度が要求されるならば、バックグラウンドの位置情
報アプリケーションとして実装し、標準位置情報サービスを利用するとよいでしょう。
Important: ユーザはどのアプリケーションについても、バックグラウンド動作を明示的に無効に
することができます。「設定(Settings)」アプリケーションで「Background App Refresh」を(すべ
てのアプリケーションに対してグルーバルに、または特定のアプリケーションに対してのみ)無
効にすれば、アプリケーションはバックグラウンドで位置情報サービスを利用することができな
くなるのです。アプリケーションがバックグラウンドで位置情報の更新を処理できるかどうかは、
UIApplicationクラスのbackgroundRefreshStatusプロパティの値をチェックすることで決定で
きます。
標準位置情報サービスのバックグラウンドでの使用
iOSアプリケーションが継続的に位置更新情報を必要とする場合、標準位置情報サービスをバックグ
ラウンドで利用する、という方法で実装できます。この機能は、ユーザをアシストする道案内やフィッ
トネス関連の動作を行うアプリケーションに最適です。この機能をアプリケーションに組み込むため
には、Xcodeプロジェクトの「Capabilities」タブで「Background Modes」をオンにし、さらに「Location」
更新モードも有効にする必要があります。標準位置情報サービスを起動/停止するコードは変わりま
せん。
システムは位置更新情報を、位置情報アプリケーションがフォアグラウンド状態のとき、バックグラ
ウンドで動作しているとき、あるいは一時停止状態のときに配送します。一時停止状態であれば、シ
ステムがこのアプリケーションを「起こし」て、更新情報を位置マネージャのデリゲートに配送した
後、迅速に一時停止状態に戻します。バックグラウンドで動作している場合、アプリケーションは新
しい位置情報データを、できるだけ小さな負荷で処理しなければなりません。
位置情報サービスが有効であれば、iOSは位置情報ハードウェアに電力を供給し、常に新しいデータ
を収集することになります。すると電池が消耗するので、位置情報データが必要なければ常に、サー
ビスを停止するようにしてください。
バックグラウンドで位置情報サービスを利用する場合、できるだけ電池の寿命が延びるよう、位置情
報マネージャオブジェクトを次のように設定してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
18
ユーザの位置の取得
バックグラウンドでの位置情報イベントの取得(iOSのみ)
●
pausesLocationUpdatesAutomaticallyプロパティをYESと設定する。このプロパティがYESで
あれば、ユーザが移動せず同じ位置にとどまっていると判断した場合など、必要に応じてCore
Locationが位置情報の更新を一時停止する(したがって位置情報ハードウェアへの電力供給を止
める)ようになります。さらに、確定した位置情報を取得できない場合にも一時停止します。
●
activityTypeプロパティに適切な値を設定する。位置情報マネージャはこの値をもとに、位置
情報の更新を停止しても問題ないかどうか判断します。たとえば曲がり角ごとに案内を行う自動
車用道案内を実現するアプリケーションの場合、このプロパティの値を
CLActivityTypeAutomotiveNavigationとすると、ユーザが一定期間内に長距離を移動しなかっ
た場合に限って位置情報の更新を停止するようになります。
●
可能であればallowDeferredLocationUpdatesUntilTraveled:timeout:メソッドを呼び出すこ
とにより、位置更新情報の配送を延期してください(“バックグラウンド状態である間の、位置情
報の更新延期” (20 ページ)を参照)。
位置情報マネージャは、位置情報の更新を停止する際、locationManagerDidPauseLocationUpdates:
メソッドで、デリゲートオブジェクトにその旨を通知します。位置情報マネージャは、位置情報の更
新を再開すると、デリゲートのlocationManagerDidResumeLocationUpdates:メソッドを呼び出し
ます。この中で何らかのタスクを実行し、あるいは状況に合わせてアプリケーションの動作を変更す
るとよいでしょう。たとえば、位置情報の更新を停止する際、デリゲートへの通知機能を利用して、
データをディスクに保存する、位置情報の更新を完全に停止する、といったことが可能です。道案内
アプリケーションであれば、次の曲がり角に達するまで、一時的にナビゲーションを無効にしてよい
か問い合わせる、といった使い方も考えられます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
19
ユーザの位置の取得
バックグラウンドでの位置情報イベントの取得(iOSのみ)
注意: ユーザあるいはシステムがアプリケーションを停止した場合、新たに位置更新情報が
届いても、システムがこれを自動的に再起動することはありません。ユーザが明示的に再起
動しない限り、位置更新情報が配送されることはないのです。自動的に再起動されるように
したければ、領域観測または大幅変更位置情報サービスを利用してください。
ただし、「Background App Refresh」の設定を(すべてのアプリケーションに対してグルー
バルに、または特定のアプリケーションに対してのみ)無効にしている場合、大幅変更や領
域観測のイベントを含め、位置に関するどのような イベントがあっても、システムがアプ
リケーションを再起動することはありません。さらに、「Background App Refresh」がオフ
であれば、アプリケーションがフォアグラウンド状態になっても、大幅変更や領域観測のイ
ベントを受信することはありません。その後、ユーザが当該アプリケーションについて
「Background App Refresh」をオンにすると、Core Locationはバックグラウンドサービスをす
べて(登録済みの領域を含む)復元します。
バックグラウンド状態である間の、位置情報の更新延期
iOS 6以降では、アプリケーションがバックグラウンドにある場合に、位置情報更新の送信を遅延する
ことができます。この機能は、アプリケーションで後から問題なく位置情報データを処理できる場合
に使用することをお勧めします。たとえば、ハイキングコースでユーザの位置情報を追跡するフィッ
トネスアプリケーションでは、ユーザが一定の距離をハイキングするまたは一定の時間が経過するま
で更新を遅延してから、一度にすべて更新することができます。更新を遅延することにより、アプリ
ケーションがより長い間スリープ状態を保てることになり、電力の節約になります。位置情報の更新
を遅延する機能では、ターゲットデバイスにGPSが存在していることが必要であるため、デバイスが
位置情報の遅延更新に対応しているかどうかを判別するために、CLLocationManagerクラスの
deferredLocationUpdatesAvailableクラスメソッドを必ず呼び出すようにしてください。
CLLocationManagerクラスのallowDeferredLocationUpdatesUntilTraveled:timeout:メソッド
で、位置情報の更新を延期できます。リスト 1-4に示すように、このメソッドは通常、位置情報マネー
ジャのデリゲートオブジェクトの、locationManager:didUpdateLocations:メソッドから呼び出す
ようにするとよいでしょう。このメソッドはハイキングアプリケーションから引用した例で、最小限
の距離を進むまで、位置情報の更新を延期します。
allowDeferredLocationUpdatesUntilTraveled:timeout:メソッドを重複して呼び出すことのな
いよう、デリゲート内部のプロパティを使って、延期しているかどうかを追跡するようになっていま
す。このメソッド内でプロパティ値をYESとし、延期していた更新が終了した時点でNOに戻します。
リスト 1-4
位置情報の遅延更新
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
20
ユーザの位置の取得
バックグラウンドでの位置情報イベントの取得(iOSのみ)
// Add the new locations to the hike
[self.hike addLocations:locations];
// Defer updates until the user hikes a certain distance
// or when a certain amount of time has passed.
if (!self.deferringUpdates) {
CLLocationDistance distance = self.hike.goal - self.hike.distance;
NSTimeInterval time = [self.nextAudible timeIntervalSinceNow];
[locationManager allowDeferredLocationUpdatesUntilTraveled:distance
timeout:time];
self.deferringUpdates = YES;
}
}
allowDeferredLocationUpdatesUntilTraveled:timeout:メソッドで指定した条件が満たされる
と、位置情報マネージャは自身のデリゲートオブジェクトの
locationManager:didFinishDeferredUpdatesWithError:メソッドを呼び出して、位置情報の遅
延更新が停止したことを通知します。位置情報マネージャは、アプリケーションが
allowDeferredLocationUpdatesUntilTraveled:timeout:メソッドを呼び出すたびに、このデリ
ゲートメソッドを正確に1回だけ呼び出します。延期期間が終了すると、位置情報マネージャは位置
更新情報を、デリゲートのlocationManager:didUpdateLocations:メソッドに配送するようになり
ます。
位置情報更新の延期を明示的に解除するには、CLLocationManagerクラスの
disallowDeferredLocationUpdatesメソッドを使います。このメソッドを実行するか、あるいは
stopUpdatingLocationメソッドで位置情報の更新そのものを停止すると、位置情報マネージャはデ
リゲートのlocationManager:didFinishDeferredUpdatesWithError:メソッドを呼び出して、位
置情報更新の延期が解除された旨を通知します。
位置情報マネージャでエラーが発生し、位置情報更新の遅延が実行できない場合、
locationManager:didFinishDeferredUpdatesWithError:デリゲートメソッドが実装されている
と、エラーの原因にアクセスできます。可能性のあるエラーのリストと、エラーの解決策(存在する
場合)については、『Core Location Constants Reference 』のCLError定数を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
21
ユーザの位置の取得
バッテリー電力節約のためのヒント
バッテリー電力節約のためのヒント
iOSベースのデバイスが位置情報データを取得するためには、相当の電力を消費します。多くのアプ
リケーションは、位置情報サービスが常時動作していなくても構わないので、必要なければサービス
を停止するだけで、簡単に消費電力を削減できます。
●
●
●
●
●
使用しない間は位置情報サービスをオフにする。分かりきったことのように思えますが、繰り返
します。曲がり角ごとに指示を出す道案内アプリケーションを除き、ほとんどのアプリケーショ
ンでは、位置情報サービスを実行したままにしておく必要はありません。位置情報サービスは、
位置情報を取得するのに必要な間だけオンにして、その後はオフにしてください。ユーザが乗り
物で移動中でない限り、現在位置は問題になるほど頻繁には変化しません。また、必要であれば
後からいつでも、位置情報サービスを再開できます。
可能な場合は、標準位置情報サービスではなく、大幅変更位置情報サービスを使用する。大幅変
更位置情報サービスでは、電力を大幅に節約しながらサービスを動かしたままにしておけます。
これは、ユーザの位置変更を追跡する必要があるけれども、標準位置情報サービスで提供される
ような高度な測地精度は必要としないアプリケーションに強く推奨されます。
アプリケーションに支障をきたさない限り、測地精度にはより低い精度を使用する。必要以上に
高い測地精度を要求すると、Core Locationは追加のハードウェアに電力を投入し、不要な精度に
対して電力を浪費することになります。アプリケーションにおいてユーザの位置を数メートルの
範囲で本当に認識する必要がある場合を除いて、desiredAccuracyプロパティに
kCLLocationAccuracyBestやkCLLocationAccuracyNearestTenMetersの値を設定しないでく
ださい。また、kCLLocationAccuracyThreeKilometersの値を指定しても、位置情報サービス
からより精度の高いデータが返されるのを避けることができません。Core Locationは、ほとんど
の場合、100メートル程度以内の測地精度で位置データを返すことができます。
一定期間を過ぎても測地精度が上がらない場合は位置情報イベントをオフにする。アプリケー
ションの受信しているイベントの測地精度が望んでいるレベルでない場合、受信しているイベン
トの測地精度を調べて、時間の経過とともに向上しているか、だいたい同じレベルを維持してい
るのかを確認します。精度が向上していなければ、望んでいる測地精度が単純にその時点では得
られていないということが考えられます。位置情報サービスをいったんオフにしておき、後で再
度試すようにすれば、アプリケーションによる電力浪費を防ぐことができます。
標準位置情報サービスを使用してバックグラウンドで位置情報データを処理するときのアプリ
ケーションの活動のタイプを指定します。アプリケーションに関連付けられている活動がどのタ
イプであるのか(たとえば、自動車用の道案内アプリケーションであるのか、それともフィット
ネスアプリケーションであるのか)をCore Locationに認識させておくことは、アプリケーション
がバックグラウンドにある場合に位置情報マネージャが位置情報の更新を停止する最適な間隔を
判別する上で役に立ちます。アプリケーションで位置情報の更新を停止するタイミングついての
位置情報マネージャの判断を支援すると、ユーザのデバイスのバッテリーの寿命が改善すること
があります。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
22
ユーザの位置の取得
バッテリー電力節約のためのヒント
●
アプリケーションがバックグラウンドにある場合に、位置情報更新の送信が遅延することを位置
情報マネージャに許可します。位置情報マネージャから受信した位置情報を更新しても、この情
報をログに記録してスリープ状態に戻る以外にアプリケーションで有効な動作を行えない場合、
更新がアプリケーションにとって意味のある状態になるまで、位置情報マネージャに更新の遅延
を許可することができます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
23
領域観測とiBeacon
Core Locationフレームワークには、特定の領域へのユーザの進入と退出を検出するために、地理的領
域の観測(iOS 4.0以降およびOS X v10.8以降)とビーコンによる領域観測(iOS 7.0以降)という2とお
りの方法が用意されています。地理的領域とは、地上にある既知の地点から特定の半径内にある円に
よって定義されるエリアのことです。これに対して、ビーコン領域とは、デバイスのBluetooth
Low-Energyビーコンへの近さによって定義されるエリアのことです。このビーコン自身は、特定の
Bluetooth Low-Energyのペイロードをアドバタイズする単純なビーコンデバイスですが、Core Bluetooth
フレームワークの支援を受けると、ご使用中のiOSデバイスをビーコンデバイスに変えることもでき
ます。
アプリケーションは地理的観測を使用して、ユーザが地理的な境界線を横断したとき、またはビーコ
ンの近傍に対して進入または退出したときに通知を受けることができます。ビーコンがiOSデバイス
の範囲内にある場合は、アプリケーションはビーコンからの相対距離を監視することもできます。こ
れらの機能を使用すると、多くの種類の革新的な位置情報活用アプリケーションを開発することがで
きます。地理的領域とビーコン領域は別のものなので、使用することに決めた領域観測のタイプに
よって、アプリケーションの使い道が決まるものと考えられます。
iOSでは、アプリケーションに関連付けられた領域は、アプリケーションが実行していないときも含
め、常に追跡されます。アプリケーションが実行していないときに、ある領域の境界線を横切ると、
アプリケーションはそのイベントを処理するためにバックグラウンドで起動されます。同様に、イベ
ントが発生したときにアプリケーションが一時停止中の場合、アプリケーションは動作させられて、
イベントを処理するために短い時間(約10秒)が割り当てられます。必要であればアプリケーション
は、UIApplicationクラスのbeginBackgroundTaskWithExpirationHandler:メソッドを使用して、
より長いバックグラウンド実行時間を要求することができます。
OS Xでは、領域観測はアプリケーションが(フォアグラウンドまたはバックグラウンドで)実行中に
ユーザのシステムが起動している場合にのみ動作します。この結果、領域に関する通知を配信するた
めにシステムがアプリケーションを起動することはありません。
領域観測の利用可否の確認
特定の領域を観測しようとする前に、アプリケーションは、現在のデバイス上で領域監視がサポート
されているかを確認するべきです。領域観測が利用できない理由はいくつか考えられます。
●
デバイスが領域観測に必要なハードウェアを備えていない。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
24
領域観測とiBeacon
領域観測の利用可否の確認
●
アプリケーションで領域観測を行うための承認をユーザが拒否している。
●
「設定(Settings)」アプリケーションで、ユーザが位置情報サービスを無効にしている。
●
●
ユーザが「設定(Settings)」アプリケーションの「Background App Refresh」をデバイスまたはアプ
リケーションのどちらかで無効にしている。
デバイスが機内モードになっていて、必要なハードウェアの電源を入れられない。
iOS 7.0以降では、領域の観測を行う前にCLLocationManagerのisMonitoringAvailableForClass:
クラスメソッドとauthorizationStatusクラスメソッドを常に呼び出す必要があります(OS X 10.8
以降とiOSの以前のバージョンでは、この代わりにregionMonitoringAvailableクラスメソッドを使
用します)。isMonitoringAvailableForClass:メソッドを使用すると、指定したクラスで領域の
観測がハードウェアでサポートされているかどうかが分かります。メソッドがNOを返した場合、この
デバイスでは領域観測を使用できません。YESが返された場合は、authorizationStatusメソッドを
呼び出して、アプリケーションに現在位置情報サービスを使用する承認が与えられているかどうかを
判別します。承認ステータスがkCLAuthorizationStatusAuthorizedの場合、アプリケーションは
登録されている任意の領域に対する境界線の横断通知を受信できます。承認ステータスがこれ以外の
値に設定されていた場合は、アプリケーションはこの通知を受信しません。
注意: アプリケーションで領域観測を使用する承認が与えられていない場合であっても、将
来使用するために領域を登録することは可能です。その後ユーザによってアプリケーション
に承認が与えられると、これらの領域に対する観測が開始され、これに続いて境界線の横断
通知が生成されるようになります。アプリケーションで承認されていない間に領域がインス
トールされたままになっていることを望まない場合は、
locationManager:didChangeAuthorizationStatus:デリゲートメソッドを使用してアプ
リケーションのステータスの変更を検出して領域を適切に削除することができます。
最後に、アプリケーションで位置情報の更新をバックグラウンドで処理する必要がある場合は、
UIApplicationクラスのbackgroundRefreshStatusプロパティを必ずチェックしてください。この
プロパティの値を使用すると、バックグラウンドでの処理か可能であるかどうかを判断することがで
き、処理できない場合はユーザに警告できます。なお、「Background App Refresh」の設定を(すべて
のアプリケーションに対してグルーバルに、または特定のアプリケーションについて)無効にしてい
る場合、領域通知のためにシステムがアプリケーションを「起こす」ことはありません。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
25
領域観測とiBeacon
地理的領域の観測
地理的領域の観測
地理的領域の観測では位置情報サービスを使用して、既知の地理的位置についてのあらゆる進入また
は退出を検出します(位置情報サービスについて詳しくは“ユーザの位置の取得” (11 ページ)を参
照)。この機能を使用して、ユーザが特定の位置に近づくとアラートを生成するなど、適切な情報を
提供できます。たとえば、所定のドライクリーニング店に近づいたとき、仕上がっている服を受け取
るよう通知するアプリケーションが考えられます。
観測する地理的領域の定義
ある地理的領域の観測を始めるには、領域を定義してそれをシステムに登録しなければなりません。
iOS 7.0以降では、CLCircularRegionクラスを使用して地理的領域を定義します(OS X v10.8以降と以
前のバージョンのiOSでは、これの代わりにCLRegionクラスを使用します)。作成する各領域には、
地理上の地域を定義するデータと、一意の識別文字列の両方が含まれている必要があります。識別文
字列は、アプリケーションが後で領域を特定するための唯一確実な方法です。領域を登録するには、
CLLocationManagerオブジェクトのstartMonitoringForRegion:メソッドを呼び出します。
リスト 2-1に、円形のMap Kitオーバーレイに基づいて新しい地理的領域を作成するメソッドの例を示
します。オーバーレイの中心点と半径がこの領域の境界線を形成しますが、半径が大きすぎて観測で
きない場合は、半径が自動的に縮小されます。作成した領域への強い参照を保存する必要ありません
が、領域の情報に後からアクセスする予定の場合は、領域の ID を保存しておく場合があります。
リスト 2-1
Map Kitオーバーレイに基づいた地理的領域の作成と登録
- (void)registerRegionWithCircularOverlay:(MKCircle*)overlay
andIdentifier:(NSString*)identifier {
// If the overlay's radius is too large, registration fails automatically,
// so clamp the radius to the max value.
CLLocationDegrees radius = overlay.radius;
if (radius > self.locManager.maximumRegionMonitoringDistance) {
radius = self.locManager.maximumRegionMonitoringDistance;
}
// Create the geographic region to be monitored.
CLCircularRegion *geoRegion = [[CLCircularRegion alloc]
initWithCenter:overlay.coordinate
radius:radius
identifier:identifier];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
26
領域観測とiBeacon
地理的領域の観測
[self.locManager startMonitoringForRegion:geoRegion];
}
地理的領域の観測は、認定済みのアプリケーションへの登録後すぐに開始されます。しかし、イベン
トをすぐに受信するものと想定しないでください。イベントが生成されるのは、境界を横断したとき
だけです。特に、登録時にユーザの位置がすでに領域の内側にある場合、位置情報マネージャはイベ
ントを自動的には生成しません。アプリケーションが領域の境界線を横断するまで待たないと、イベ
ントが生成されてデリゲートに送信されることはありません。ユーザが領域境界内にいるかどうか判
断するためには、CLLocationManagerクラスのrequestStateForRegion:メソッドを使います。
観測する一連の領域を指定するときには常に慎重に検討してください。領域は共有のシステムリソー
スであり、システム全体で利用可能な領域の総数は限られています。このため、Core Locationは、1つ
のアプリケーションで同時に観測できる領域の数を20に制限しています。このような制限を回避する
には、ユーザの近隣の領域のみ登録することを検討してください。ユーザの位置が変わるのにつれ
て、距離の遠くなった領域を削除し、ユーザの進路上で近づいている領域を追加することができま
す。領域を登録しようとしたときに空きがないと、位置情報マネージャはデリゲートの
locationManager:monitoringDidFailForRegion:withError:メソッドを呼び出して、エラーコー
ドkCLErrorRegionMonitoringFailureを渡します。
地理的領域の境界線横断イベントの処理
デフォルトでは、ユーザの現在位置が境界領域を横断するたびに、システムはアプリケーションに対
して適切な領域イベントを生成します。アプリケーションは、次のメソッドを実装して境界線の横断
を処理することができます。
●
locationManager:didEnterRegion:
●
locationManager:didExitRegion:
領域を定義して登録するときに、CLRegionクラスのnotifyOnEntryプロパティとnotifyOnExitプロ
パティを明示的に設定するとアプリケーションに通知される境界線横断のオベントをカスタマイズで
きます、(プロパティのデフォルト値はどちらもYESになります)。たとえば、ユーザが領域の境界
線から退出したときにのみ通知が必要な場合は、領域のnotifyOnEntryプロパティの値をNOに設定し
ます。
システムは、境界線に加え、システムで定義された緩衝距離を越えるまで境界線の横断を報告しませ
ん。緩衝距離は、ユーザが境界線付近を移動しているときに、システムが大量の進入・退出イベント
を立て続けに生成するのを防ぐための値です。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
27
領域観測とiBeacon
ビーコン領域の観測
領域の境界線を横断したときの最も可能性の高い応答は、対象物に接近していることをユーザに知ら
せることです。アプリケーションがバックグラウンドで実行中の場合、ローカル通知を使用してユー
ザに知らせることができます。それ以外の場合は単にアラートを送信できます。
ビーコン領域の観測
ビーコン領域の観測では、iOSデバイスに内蔵されている無線を使用して、ユーザがiBeacon情報をア
ドバタイズしているBluetooth Low-Energyデバイスの近くにいることを検出します。地理的領域の観測
と同様に、この機能を使用して、ユーザがビーコン領域に対して侵入または退出した場合に、アラー
トの生成やその他の適切な情報提供を行うことができます。ただし、ビーコン領域は、固定された地
理的座標ではなく、次の値の組み合わせをアドバタイズするBluetooth Low-Energyビーコンとの近接度
によって識別されます。
●
128ビットの値である近接UUID(universally unique identifier)は、特定のタイプまたは特定の組織
によって発信されているものとして、1つ以上のビーコンを一意に識別します。
●
16ビットの符号なし整数であるメジャー値は、同じ近接UUIDを持つビーコンをグループ化するた
めに使用されます。
●
16ビットの符号なし整数であるマイナー値は、同じ近接UUIDと同じメジャー値を持つビーコンを
区別するために使用されます。
同じビーコン領域が複数のビーコンを表すこともできるので、ビーコン領域の観測機能を活用する、
興味深い用途がいくつかあります。たとえばあるデパートの顧客サービス専用アプリケーションで
は、同じ近接UUIDを使って、チェーン店すべてを観測できます。ユーザがある店舗に近づくと、アプ
リケーションはその店のビーコンを検出し、メジャー値とマイナー値に基づいて、検出した具体的な
店舗や、その中の売り場などといった事項を判断します(なお、ビーコンは近接UUIDを常にアドバタ
イズしますが、メジャー値やマイナー値は必要に応じて行うだけです)。
観測するビーコン領域の定義
あるビーコン領域の観測を始めるには、領域を定義してそれをシステムに登録しなければなりませ
ん。ビーコン領域は、CLBeaconRegionクラスの適切な初期化メソッドで定義します。CLBeaconRegion
オブジェクトを生成する際には、観測するビーコンの、proximityUUID、major、minorの各プロパ
ティを指定します(近接UUIDは必須、それ以外は必要な場合のみ)。さらに、コード中で参照できる
よう、領域を一意に識別する文字列を指定しなければなりません。なお、領域の識別文字列は、ビー
コンがアドバタイズする識別情報とは無関係です。
ビーコン領域を登録するには、CLLocationManagerオブジェクトのstartMonitoringForRegion:メ
ソッドを呼び出します。ビーコン領域を作成して登録するメソッドの例をリスト 2-2に示します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
28
領域観測とiBeacon
ビーコン領域の観測
リスト 2-2
ビーコン領域の作成と登録
- (void)registerBeaconRegionWithUUID:(NSUUID *)proximityUUID
andIdentifier:(NSString*)identifier {
// Create the beacon region to be monitored.
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc]
initWithProximityUUID:proximityUUID
identifier:identifier];
// Register the beacon region with the location manager.
[self.locManager startMonitoringForRegion:beaconRegion];
}
地理的領域の観測と同様に、ビーコン領域の観測は、認定済みのアプリケーションへの登録直後に開
始されます。ユーザのデバイスが、登録されたビーコン領域(近接UUID、メジャー値、マイナー値)
によって定義された識別情報をアドバタイズしているビーコンを検出すると、システムはアプリケー
ションに対して適切な領域イベントを生成します。
注意: ビーコン領域をUUID値のみで設定するのも珍しいことではありません。この場合、
指定されたUUIDのビーコン範囲内にデバイスが入ると、領域がアクティブになります。ビー
コン領域に入ったら、ビーコンまでの距離を測定し、近隣にある個別のビーコンに関する詳
細情報を取得することになります。ビーコンの距離測定について詳しくは、“ビーコンの距
離測定を使用したビーコンまでの距離の決定” (30 ページ)を参照してください。
ビーコン領域の境界線横断イベントの処理
登録済みのビーコン領域にユーザが進入すると、位置情報マネージャはデリゲートオブジェクトの
locationManager:didEnterRegion:を呼び出します。同様に、登録済みのすべてのビーコン領域内
からユーザがいなくなった場合にも、位置情報マネージャはデリゲートオブジェクトの
locationManager:didExitRegion:を呼び出します。なお、ユーザが領域境界を横切らなければ、
上記のメソッドが呼び出されることはありません。特に、ユーザが既に領域内にいる場合、位置情報
マネージャがlocationManager:didEnterRegion:を呼び出すことはありません。これらのデリゲー
トメソッドは、ユーザの接近を知らせる、またはある位置に固有のUIを表示するために実装すること
ができます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
29
領域観測とiBeacon
ビーコン領域の観測
実際にアプリケーションに通知する境界横断イベントは、ビーコン領域のnotifyOnEntryプロパティ、
notifyOnExitプロパティで指定できます(プロパティのデフォルト値はどちらもYESになります)。
たとえば、ユーザが領域の境界線から退出したときにのみ通知が必要な場合は、領域のnotifyOnEntry
プロパティの値をNOに設定します。
ユーザがデバイスのディスプレイをオンにするまで、ユーザのビーコン領域への進入の通知を遅らせ
ることも可能です。これを行うには、ビーコン領域の登録時に、ビーコン領域の
notifyEntryStateOnDisplayプロパティの値をYESに設定(そして領域のnotifyOnEntryプロパティ
をNOに設定)するだけです。ユーザに通知が何回も送信されるのを防止するには、領域への進入ごと
に1回だけ位置に関する通知を配信するようにします。
ビーコンの距離測定を使用したビーコンまでの距離の決定
ユーザのデバイスが登録済みのビーコン領域の内部にある場合、アプリケーションでは
CLLocationManagerクラスのstartRangingBeaconsInRegion:メソッドを使用して、領域内の1つ以
上のビーコンとの相対的な距離を決定し、この距離が変化したときに通知を行うことができます(ビー
コン領域内でビーコンとの距離測定を行う前には、必ずCLLocationManagerクラスの
isRangingAvailableクラスメソッドを呼び出す必要があります)。ビーコンとの相対距離を把握し
ていることは、多くのアプリケーションにとって役に立ちます。たとえば、博物館を考えてみましょ
う。展示物ごとにビーコンが置いてあります。博物館の専用アプリケーションは、展示物との距離を
手がかりに、該当する展示物に関する情報を表示します。
位置情報マネージャは、指定したビーコン領域にあるビーコンが範囲内に入った場合、範囲外に出た
場合、あるいは距離が変わった場合に、デリゲートオブジェクトの
locationManager:didRangeBeacons:inRegion:を呼び出します。このデリゲートメソッドには、
現在範囲内にあるビーコンを表す、CLBeaconオブジェクトの配列が用意されています。このビーコ
ンの配列は、最も近くにあるビーコンが配列の先頭にあるように、デバイスからの距離によって整列
されています。これらのオブジェクトにある各ビーコンについての情報を使用して、各ビーコンとの
距離を決定することができます。CLBeaconオブジェクトのproximityプロパティ値には、一般的な
意味におけるビーコンとの相対距離が与えられます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
30
領域観測とiBeacon
ビーコン領域の観測
注意: ビーコンの距離測定は、Bluetooth Low-Energy無線信号の強度検出に依存し、信号の
精度は、壁や扉などの物体によって上下します。信号は水分の影響を受けるので、人体も影
響を与えることになります。iBeaconの配備計画においては、この要因を認識しておくこと
が重要です。各ビーコンが報告するproximity値に影響を与えることになるからです。配備
の際には、必要ならば、各CLBeaconオブジェクトが報告するaccuracy値およびrssi値に基
づき、ビーコンの配置を調整してください。
先に説明した博物館アプリケーションを元に作成されたリスト 2-3のコードには、ユーザのデバイス
からの相対距離を決定するためにproximityプロパティを使用する方法が示されています。このコー
ドは、配列で最も近くにあるビーコンとの相対距離がユーザに比較的近い(CLProximityNear定数に
よって定義される)場合に、博物館の特区の展示物についての詳細な情報を提示するUIを表示しま
す。
リスト 2-3
ビーコンとデバイスの相対距離を判定するコード例
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(CLBeaconRegion *)region {
if ([beacons count] > 0) {
CLBeacon *nearestExhibit = [beacons firstObject];
// Present the exhibit-specific UI only when
// the user is relatively close to the exhibit.
if (CLProximityNear == nearestExhibit.proximity) {
[self presentExhibitInfoWithMajorValue:nearestExhibit.major.integerValue];
} else {
[self dismissExhibitInfo];
}
}
一貫した結果が得られるよう、ビーコンの距離測定は、アプリケーションがフォアグラウンド状態の
間のみ行うようにしてください。アプリケーションがフォアグラウンド状態であれば、おそらくデバ
イスはユーザが手に持っており、ビーコンまでの間に視界を遮るものはあまりないでしょう。フォア
グラウンド状態で実行すれば、電池の寿命を延ばすことにもなります。ユーザが実際にデバイスを
使っている間だけ、入ってくるビーコン信号を処理することになるからです。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
31
領域観測とiBeacon
iOSデバイスをiBeaconとして利用
注意: 複数のビーコンデバイスが近接UUIDとメジャー値、マイナー値の同じ組み合わせを
アドバタイズしている場合は、これらのビーコンデバイスは異なる相対距離にあると
locationManager:didRangeBeacons:inRegion:メソッドによって報告されることがあり
ます。各ビーコンはそれぞれ一意に識別できるようにすることをお勧めします。
さらに、ビーコンデバイスとして設定されているiOSデバイスとの距離測定を行う場合は、
locationManager:didRangeBeacons:inRegion:メソッドが1台ではなく、(同じ近接UUID、
メジャー値、マイナー値を持つ)2台のデバイスを報告する場合が短期間存在します。この
動作の原因は、iOSデバイスのBluetooth識別子がプライバシーの関係上、定期的に変更され
ることにあります。元のBluetooth識別子に基づいているproximityプロパティは、識別子の
変更後2秒位内である場合はCLProximityUnknownの値を報告します。この識別子は10秒位
内に解決され、1つの心形領域のみが報告されるようになります。
iOSデバイスをiBeaconとして利用
Bluetooth Low-Energyによるデータ共有に対応したiOSデバイスはすべて、ビーコンデバイスとして使
うことができます。アプリケーションはフォアグラウンドで動作しなければならないので、iOSデバ
イスでもiBeaconの処理は可能ですが、これはテスト目的か、POSアプリケーションのように常にフォ
アグラウンドで動作するものに限ります。それ以外の目的でiBeaconを実装する場合、サードパーティ
からビーコンとして使える専用ハードウェアを入手する必要があります。
iOSデバイスをビーコンデバイスにするには、Core Bluetoothフレームワークを使用する必要があるた
め、XcodeプリジェクトにあるアプリケーションがCoreBluetooth.frameworkにリンクされているこ
とを確認してください。このフレームワークのクラスとヘッダにアクセスするには、関連するソース
ファイルの先頭に#import <CoreBluetooth/CoreBluetooth.h>ステートメントを追加します。
ビーコン領域の作成とアドバタイズ
iOSデバイスをビーコンとして使用するには、最初にビーコン領域の近接UUIDとして使用できる128
ビットのUUIDを生成する必要があります、ターミナルを開き、「uuidgen」と入力してください。次
の例のような、ハイフンで区切られたASCII文字列の形式で、一意の128ビット値が得られます。
$ uuidgen
39ED98FF-2900-441A-802F-9C398FC199D2
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
32
領域観測とiBeacon
iOSデバイスをiBeaconとして利用
次に、ビーコンの近接UUID用に生成したこのUUIDを使用して、ビーコン領域を作成します。このと
き、必要であればメジャー値とマイナー値を定義します。新しい領域では一意の文字列識別子も使用
されていることを確認します。このコードは、先のUUIDの例を使用して新しいビーコン領域を作成す
る方法を示します。
NSUUID *proximityUUID = [[NSUUID alloc]
initWithUUIDString:@"39ED98FF-2900-441A-802F-9C398FC199D2"];
// Create the beacon region.
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc]
initWithProximityUUID:proximityUUID
identifier:@"com.mycompany.myregion"
ビーコン領域を作成したら、Core BluetoothフレームワークのCBPeripheralManagerクラスを使用し
て、ビーコンの近接UUID(および指定したメジャー値とマイナー値)をアドバタイズする必要があり
ます。Core Bluetoothでは、ペリフェラル とはBluetooth Low-Energyを使用してアドバタイズとデータ
の共有を行うデバイスのことです。ビーコンのデータをアドバタイズすることは、他のデバイスが
ビーコンを検出して距離を測定するための唯一の手段です。
Core Bluetoothでペリフェラルデータをアドバタイズするには、CBPeripheralManagerオブジェクト
のインスタンスにあるCBPeripheralManagerクラスのstartAdvertising:メソッドを呼び出すこと
ができます。このメソッドではアドバタイズデータの辞書(NSDictionaryのインスタンス)がある
ことを前提にしています。次の例に示すように、CLBeaconRegionクラスの
peripheralDataWithMeasuredPower:メソッドを使用して、Core Bluetoothがペリフェラルとしてビー
コンをアドバタイズするために必要な他の情報とともにビーコンの識別情報をエンコードする辞書を
取得します。
// Create a dictionary of advertisement data.
NSDictionary *beaconPeripheralData =
[beaconRegion peripheralDataWithMeasuredPower:nil];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
33
領域観測とiBeacon
iOSデバイスをiBeaconとして利用
注意: 上に示したコードでは、nilの値をmeasuredValueパラメータに渡します。これは1
メートル離れた位置における(デシベル単位で測定した)受信信号の強さの指標(RSSI)の
値を表しています。この値は距離を測定する際に使用されます。nilを指定すれば、デバイ
スのデフォルト値を使用することになります。特定の環境において、距離測定のパフォーマ
ンスの精度を上げるためにデバイスのより正確な較正を必要とする場合は、オプションとし
てRSSI値を指定できます。
次にCBPeripheralManagerクラスのインスタンスを作成し、次のコード例のように、他のデバイス
から検出されるようアドバタイズを行います。
// Create the peripheral manager.
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc]
initWithDelegate:selfqueue:nil options:nil];
// Start advertising your beacon's data.
[peripheralManager startAdvertising:beaconPeripheralData];
Important: ペリフェラルマネージャオブジェクトを作成すると、ペリフェラルマネージャはデリ
ゲートオブジェクトのperipheralManagerDidUpdateState:メソッドを呼び出します。このデリ
ゲートメソッドは、Bluetooth Low-Energyがサポートされ、ローカルのペリフェラルデバイスで使
用可能であることを確認するために実装する必要があります。このデリゲートメソッドの詳細に
ついては、『CBPeripheralManagerDelegate Protocol Reference 』を参照してください。
アプリケーションをビーコンとしてアドバタイズした後、アプリケーションをフォアグラウンド状態
のまま稼働させ、必要なBluetooth信号をブロードキャストする必要があります。ユーザがアプリケー
ションを停止すると、システムはデバイスをペリフェラルとしてアドバタイズすることをやめます。
ペリフェラルマネージャを使用してBluetooth Low-Energyを使用したデータのアドバタイズを行う方法
の詳細については、『CBPeripheralManagerClassReference 』および『CoreBluetoothProgrammingGuide 』
を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
34
領域観測とiBeacon
iOSアプリケーションの領域観測サポートのテスト
iOSアプリケーションの領域観測サポートのテスト
iOSシミュレータまたはデバイスで領域観測コードのテストを行う場合は、領域の境界線が横断され
てもすぐには領域イベントが発生しないことがあることを理解しておいてください。不確かな通知が
行われるのを避けるために、iOSでは一定のしきい値条件が満たされないと領域通知を行いません。
特に、ユーザの位置が領域の境界線を横断し、この境界線から最小距離だけ離れてから、この位置を
少なくとも20秒間保持しないと、通知は報告されません。
この距離のしきい値は、ハードウェアと現在使用可能な位置情報テクノロジーとによって決められて
います。たとえば、Wi-Fiが無効になっている場合、領域観測の精度は大幅に低下します。しかしなが
ら、テスト目的の場合は、最小距離は約200メートルであると仮定することができます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
35
デバイスのヘディングとコースの取得
Core Locationは、方向関連の情報を取得する方法を2とおりサポートしています。
●
●
磁力センサー付きのデバイスは、デバイスが指している方角(ヘディングともいいます)を報告
することができます。
GPSハードウェア付きのデバイスは、デバイスが進行している方向(コースともいいます)を報
告することができます。
ヘディングとコースの情報は、同じ情報を示すものではありません。デバイスのヘディングは、真北
または磁北を基準とするデバイスの実際の向きを示します。デバイスのコースが表すのは移動方向で
あり、デバイスの向きは考慮されません。アプリケーションに応じて、どちらか都合の良い情報を使
うことも、両方を組み合わせて使うこともできます。たとえば、道案内アプリケーションであれば、
ユーザの現在の速度に応じてコース情報とヘディング情報を切り替えることができます。歩行速度で
は、現在の環境に対してユーザを正しい方角に向けるためにヘディング情報が有効ですが、車の場
合、コース情報により車が移動するおおよその方向が示されます。
方向関連のイベントのための要件の追加
iOSアプリケーションを正しく機能させるために方向関連情報を必要とする場合は、アプリケーショ
ンのInfo.plistファイルにUIRequiredDeviceCapabilitiesキーを追加する必要があります。この
キーには、アプリケーションがiOSベースデバイスに対して要求する機能を示す文字列の配列が含ま
れます。App Storeはこの情報を利用して、ハードウェアの最小要件を満たしていないデバイスにユー
ザがアプリケーションをインストールしてしまうのを防ぎます。
方向関連のイベントに関しては、UIRequiredDeviceCapabilitiesキーに関連付けることのできる
文字列が2つあります。
●
magnetometer - アプリケーションがヘディング情報を必要とする場合はこの文字列を指定しま
す。
●
gps - アプリケーションがコース関連の情報を必要とする場合はこの文字列を指定します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
36
デバイスのヘディングとコースの取得
方角(ヘディング)関連イベントの取得
Important: iOSアプリケーションがヘディングまたはコースのイベントを使用するけれども、それ
らがなくてもアプリケーションが正常に動作する場合は、対応する文字列を
UIRequiredDeviceCapabilitiesキーに指定しないでください。
どちらの場合も、文字列「location-services」も配列に含めます。UIRequiredDeviceCapabilities
キーの詳細については、『Information Property List Key Reference 』を参照してください。
方角(ヘディング)関連イベントの取得
ヘディングイベントは、磁力センサーを備えたデバイス上で実行されるアプリケーションで利用でき
ます。磁力センサーは地球から発生する近辺の磁場を測定し、デバイスの正確な向きを識別します。
磁力センサーは局所的な磁場(オーディオスピーカー、モーター、その他の電子機器に含まれる固定
磁石から発生する磁気など)の影響を受ける可能性がありますが、Core Locationフレームワークはデ
バイスとともに移動する磁場を除外するように十分に高性能にできています。
ヘディング値は、磁北または地図上の真北のどちらを基準にしても報告させることができます。磁北
は、地球の表面上で、地球の磁場が発生する地点を表します。この位置は、真北を表す北極点と同じ
ではありません。デバイスの位置にもよりますが、磁北は多くの用途に十分に適しています。ただし
北極点に近づくほどこの値の有用性は低くなります。
ヘディングイベントを取得するには:
1.
CLLocationManagerオブジェクトを作成します。
2.
headingAvailableクラスメソッドを呼び出して、ヘディングイベントが利用可能かを確認しま
す。
3.
位置情報マネージャオブジェクトにデリゲートオブジェクトを割り当てます。
4.
真北を基準にした値が必要な場合は、位置情報サービスを開始します。
5.
startUpdatingHeadingメソッドを呼び出してヘディングイベントの送信を開始します。
リスト 3-1に、位置情報マネージャを設定し、ヘディングイベントの送信を開始するカスタムメソッ
ドを示します。この場合、オブジェクトは現在の方角(ヘディング)をユーザに表示するView Controller
です。View Controllerは真北を基準にしたヘディング値を表示するため、ヘディングの更新に加えて
位置情報の更新も開始します。
リスト 3-1
ヘディングイベントの送信を開始する
- (void)startHeadingEvents {
if (!self.locManager) {
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
37
デバイスのヘディングとコースの取得
方角(ヘディング)関連イベントの取得
CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
// Retain the object in a property.
self.locManager = theManager;
locManager.delegate = self;
}
// Start location services to get the true heading.
locManager.distanceFilter = 1000;
locManager.desiredAccuracy = kCLLocationAccuracyKilometer;
[locManager startUpdatingLocation];
// Start heading updates.
if ([CLLocationManager headingAvailable]) {
locManager.headingFilter = 5;
[locManager startUpdatingHeading];
}
}
CLLocationManagerDelegateデリゲートプロパティに割り当てるオブジェクトは、プロトコルに従
わなければなりません。新しいヘディングイベントが届いたら、ロケーションマネージャオブジェク
トはlocationManager:didUpdateHeading:メソッドを呼び出してそのイベントをアプリケーション
に送信します。新しいイベントを受信するときは、リスト 3-2に示すように、headingAccuracyプロ
パティをチェックして、今受信したデータが有効であることを確認してください。さらに、真北を基
準にしたヘディング値を使用する場合は、使用前に有効な値が含まれていることも確認します。
リスト 3-2
ヘディングイベントを処理する
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading
*)newHeading {
if (newHeading.headingAccuracy < 0)
return;
// Use the true heading if it is valid.
CLLocationDirection
theHeading = ((newHeading.trueHeading > 0) ?
newHeading.trueHeading : newHeading.magneticHeading);
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
38
デバイスのヘディングとコースの取得
ユーザーの移動中にコース情報を取得する
self.currentHeading = theHeading;
[self updateHeadingDisplays];
}
ユーザーの移動中にコース情報を取得する
GPSハードウェアを備えたデバイスは、デバイスの現在のコースと速度を示す情報を生成することが
できます。コース情報はデバイスの移動方向を表し、必ずしもデバイスそのものの向きを反映しませ
ん。そのため、コース情報は、ユーザが移動している最中にナビゲーション情報を提供するアプリ
ケーションを主な対象としています。
実際のコースと速度の情報は、ユーザの位置の取得に使用するのと同じCLLocationオブジェクトを
使用してアプリケーションに返されます。位置情報の更新を開始すると、Core Locationは、入手可能
な場合はコースと速度の情報を自動的に提供します。Core Locationフレームワークは、受信した位置
情報を使用して現在の移動方向を計算します。位置情報の更新を開始する方法の詳細については、
“ユーザの位置の取得” (11 ページ)を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
39
位置データのジオコーディング
位置データは通常、地球上のある地点に対応する緯度と経度を表す一組の数値として返されます。こ
のような座標値は、コード内で位置データを正確かつ簡単に指定する手段となりますが、ユーザに
とっては直観的ではありません。ユーザには、グローバルな座標ではなく、番地、市区町村、州、
県、国のように親しみのある情報を用いて示された位置のほうが理解しやすいでしょう。ユーザに親
しみやすい方法で位置情報を表示する必要がある状況では、Geocoderオブジェクトを使用してその情
報を取得することができます。
Geocoderオブジェクトについて
Geocoderオブジェクトは、緯度/経度と、ユーザに親しみのあるプレースマーク、すなわち番地、市
区町村、州、県、国などの一連のデータとの間で変換を行うネットワークサービスを使用します。逆
ジオコーディングとは、緯度と経度をプレースマークに変換する処理です。正ジオコーディングと
は、プレース名情報を緯度と経度の値に変換する処理です。逆ジオコーディングはどの版のiOSでも
使えますが、正ジオコーディングはiOS 5.0以降でしか使えません。正逆のジオコーディングは、OS X
v10.8以降で利用できます。
注意: 名称や住所、施設の種類によって地図上の位置を検索できるようにしたい場合は、
MKLocalSearchのAPI群が役に立つでしょう。ローカル検索機能をアプリケーションに組み
込む手順については、“検索機能の組み込み” (92 ページ)を参照してください。
Geocoderはネットワークサービスに依存するため、ジオコーディング要求が成功するためには有効な
ネットワーク接続が必要です。デバイスが機内モードにある場合や、ネットワークが現在設定されて
いない場合、Geocoderは必要なサービスに接続できないので、結果として適切なエラーを返す必要が
あります。ジオコーディング要求の作成時に適用すべき経験則をいくつか示します。
●
●
●
送信する逆ジオコーディング要求は、1つのユーザアクションに対して多くとも1つ程度にする。
ユーザが、同じ場所のジオコーディングを含む複数のアクションを実行した場合は、アクション
ごとに個別の要求を開始するのではなく、最初のジオコーディング要求から返された結果を再利
用する。
位置情報を自動的に更新する必要がある場合(ユーザが移動中のときなど)は、ユーザの位置が
大幅に変わったときと、適度な時間が経過したあとにのみジオコーディング要求を再発行する。
一般に、ジオコーディング要求を1分間に2回以上送信するのは避けてください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
40
位置データのジオコーディング
CLGeocoderでプレースマーク情報を取得
ユーザが結果をすぐに確認しないときには、ジオコーディング要求を開始しない。たとえば、ア
プリケーションがバックグラウンドで動作しているときや、割り込みを受けて現在非アクティブ
状態であるときは、要求を開始しないでください。
●
CLGeocoderでプレースマーク情報を取得
CLGeocoderクラスを使って逆ジオコーディング要求を開始するには、このクラスのインスタンスを
作成して、reverseGeocodeLocation:completionHandler:メソッドを呼び出します。ジオコーダ
オブジェクトは逆ジオコーディング要求を非同期に開始し、結果を提供されたブロックオブジェクト
に送ります。ブロックオブジェクトは、要求に対する結果が成功でも失敗でも実行されます。失敗で
あれば、その理由を示すエラーオブジェクトがブロックに渡されます。
注意: 同じCLGeocoderオブジェクトを使って、ジオコーディング要求をいくつでも開始で
きますが、同じジオコーダに関して同時にアクティブになる要求は1つだけです。
リスト 4-1には、地図上の地点を逆ジオコーディングする方法の例が示されます。ジオコーディング
に特有のコードは最初の数行だけで、ここでは必要に応じてジオコーダオブジェクトを割り当て、
reverseGeocodeLocation:completionHandler:メソッドを呼び出して、逆ジオコーディング処理
を起動しています(geocoder変数はジオコーダオブジェクトを格納するメンバ変数)。残りのコー
ドはサンプルアプリケーション自身に特有のものです。この場合、サンプルアプリケーションはプ
レースマークを、独自の注釈オブジェクト(MapLocationクラスで定義される)とともに格納し、対
応する注釈ビューの吹き出しにボタンを追加します。
リスト 4-1
CLGeocoderを用いた位置のジオコーディング
@implementation MyGeocoderViewController (CustomGeocodingAdditions)
- (void)geocodeLocation:(CLLocation*)location forAnnotation:(MapLocation*)annotation
{
if (!geocoder)
geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:
^(NSArray* placemarks, NSError* error){
if ([placemarks count] > 0)
{
annotation.placemark = [placemarks objectAtIndex:0];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
41
位置データのジオコーディング
プレース名を座標に変換する
// Add a More Info button to the annotation's view.
MKPinAnnotationView* view = (MKPinAnnotationView*)[map
viewForAnnotation:annotation];
if (view && (view.rightCalloutAccessoryView == nil))
{
view.canShowCallout = YES;
view.rightCalloutAccessoryView = [UIButton
buttonWithType:UIButtonTypeDetailDisclosure];
}
}
}];
}
@end
サンプルではこのようにブロックオブジェクトを使っているため、(注釈オブジェクトなどの)情報
に容易にアクセスし、完了ハンドラの一部として使えるという利点があります。ブロックがなかった
とすれば、データ変数を獲得するプロセスは、より複雑になっていたはずです。
プレース名を座標に変換する
CLGeocoderクラスを使い、Address Book情報の辞書、または単なる文字列を指定して、正ジオコー
ディング要求を行います。文字列ベースの要求に、専用の書式はありません。区切り文字は、あれば
分かりやすくなりますが、なくても構いません。ジオコーダサーバは文字列を、大文字と小文字の区
別がないものとして扱います。たとえば以下のような文字列で、それに応じた結果が得られます。
●
「Apple Inc」
●
「1 Infinite Loop」
●
「1 Infinite Loop, Cupertino, CA USA」
正ジオコーダに与える情報が多いほど、よい結果が得られます。ジオコーダオブジェクトは、与えら
れた情報をパースし、合致が見つかれば、プレースマークオブジェクトをいくつか返します。返され
るプレースマークオブジェクトの個数は、与えられた情報の具体性に大きく依存します。したがっ
て、通り、市、県、国の情報が揃っていれば、通りと市の情報しかない場合に比べ、単一の住所を返
す可能性が高くなります。ジオコーダに渡す完了ハンドラブロックは、次のように、複数のプレース
マークが返された場合にも対処できるようでなければなりません。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
42
位置データのジオコーディング
プレース名を座標に変換する
[geocoder geocodeAddressString:@"1 Infinite Loop"
completionHandler:^(NSArray* placemarks, NSError* error){
for (CLPlacemark* aPlacemark in placemarks)
{
// Process the placemark.
}
}];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
43
地図の表示
Map Kitフレームワークを利用すると、完全な機能を備えた地図インターフェイスをアプリケーション
ウインドウに埋め込むことができます。このフレームワークが提供する地図サポートには、iOSとOS
Xのどちらでも動作する、「マップ(Maps)」アプリケーションのさまざまな機能が含まれています。
標準的なストリートレベルの地図情報、航空写真、またはこれら2つの組み合わせを表示できます。
地図に拡大縮小、パン、傾斜を施すプログラムを記述できます。また、建物を3D表示し、独自の情報
を「注釈」として添えることも可能です。また、Map Kitフレームワークは、ユーザによる地図の拡大
縮小やパンを可能にするタッチイベントを自動的にサポートします。
Map Kitフレームワークの機能を使用するには、XcodeプロジェクトでMaps機能を有効にする必要があ
ります(さらに、そのためには適切なエンタイトルメントをApp IDに追加しなければなりません)。
地図ベースのアプリケーションを配布するためには、iOS App StoreまたはMac App Storeを通さなけれ
ばなりません。エンタイトルメント、コード署名、プロビジョニングについて十分に把握していない
場合は、『App Distribution Quick Start 』に目を通してください。Map Kitフレームワークのクラスの全
般的な情報については、『Map Kit Framework Reference 』を参照してください。
Important: iOS 5.1以前では、Map KitフレームワークはGoogleサービスを使用して地図データを提
供してします。このフレームワークとそれに関連するインターフェイスを使用する場合は、Google
Maps/Google Earth APIの利用規約に従わなければなりません。これらの利用規約は
http://code.google.com/apis/maps/iphone/terms.htmlで参照できます。
地図ジオメトリの理解
Map Viewには、球状のオブジェクト、すなわち地球を平面化した表現が含まれています。地図を効果
的に使用するには、Map View上で点を指定する方法と、その点を地球の表面上の点に変換する方法を
理解しておく必要があります。地図の座標系を理解することは、オーバーレイのように地図上にカス
タムコンテンツを重ねて配置する予定がある場合は特に重要です。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
44
地図の表示
地図ジオメトリの理解
地図の座標系
Map Kitで使用される座標系を理解するには、地球の3次元の表面が2次元の地図にマッピングされる仕
組みを理解すると役に立ちます。図 5-1は、地球の表面がどのように2次元平面にマッピングされるか
を示します。
図 5-1
球状データから平面へのマッピング
Map Kitではメルカトル図法、すなわち図 5-1に示したような、特殊なタイプの円筒図法を使用してい
ます。円筒図法では、球の座標が円筒の面にマッピングされ、その円筒が展開されて平面地図になり
ます。このような投影図では、本来は極に収斂する経度線が、代わりに平行に並ぶため、赤道から離
れるほど大陸は変形します。メルカトル図法の利点は、一般的なナビゲーションに有効な方法で地図
の内容が拡大縮小される点です。具体的には、メルカトル図法では、地図上の任意の2点間に引いた
直線から、地球の表面上での実際のナビゲーションで使用することのできる進路方向を求めることが
できます。Map Kitで用いられている投影法では、グリニッジ子午線を中心子午線として使用します。
地図上でデータ点を指定する方法は、そのデータ点の用途により異なります。Map Kitは、地図上の
データ点を指定するために基本的な3つの座標系をサポートしています。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
45
地図の表示
地図ジオメトリの理解
●
●
●
地図座標は、地球の球状表現上の緯度と経度です。地図座標は、地球上の場所を指定する基本的
な方法です。個々の地図座標の値は、CLLocationCoordinate2D構造体を使用して指定します。
領域を指定するには、MKCoordinateSpan構造体およびMKCoordinateRegion構造体を使用しま
す。
地図点は、メルカトル図法の地図上のxおよびy値です。地図点は、必要な数学計算が平易である
ことから、多くの地図関連の計算において地図座標の代わりに使用されます。アプリケーション
では、地図上のカスタムオーバーレイの形状と位置を指定する際に、主に地図点を使用します。
個々の地図点は、MKMapPoint構造体を使用して指定します。領域を指定するには、MKMapSize構
造体およびMKMapRect構造体を使用します。
点は、ビューオブジェクトの座標系に関連付けられた図形単位です。地図点と地図座標は、ビュー
にカスタムコンテンツを描画する前に点にマッピングされなければなりません。個々の点は、
CGPoint構造体を使用して指定します。領域を指定するには、CGSize構造体およびCGRect構造体
を使用します。
ほとんどの状況では、使用すべき座標系は、使用しているMap Kitインターフェイスによってあらかじ
め決められます。実際のデータをファイルまたはアプリケーション内に保存することに関して言え
ば、位置データの保存には地図座標が正確かつポータブルであり最も適しています。また、Core
Locationも位置の値を指定する際に地図座標を使用します。
座標系の変換
通常、地図上の点は緯度と経度の値を使用して指定しますが、異なる座標系との間で変換が必要な場
合もあります。たとえば、通常はオーバーレイの形状を指定する際に地図点を使用します。表 5-1に、
異なる座標系への変換に使用する変換ルーチンの一覧を示します。これらの変換処理のほとんどは、
点への変換または点からの変換を伴うため、ビューオブジェクトを必要とします。
表 5-1
地図座標系変換ルーチン
変換元
変換先
変換ルーチン
地図座標
点
convertCoordinate: toPointToView:(MKMapView)
convertRegion: toRectToView:(MKMapView)
地図座標
地図点
MKMapPointForCoordinate
地図点
地図座標
MKCoordinateForMapPoint
MKCoordinateRegionForMapRect
地図点
点
pointForMapPoint:(MKOverlayRenderer)
rectForMapRect:(MKOverlayRenderer)
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
46
地図の表示
ユーザインターフェイスへのMap Viewの追加
変換元
変換先
変換ルーチン
点
地図座標
convertPoint: toCoordinateFromView:(MKMapView)
convertRect: toRegionFromView:(MKMapView)
点
地図点
mapPointForPoint:(MKOverlayRenderer)
mapRectForRect:(MKOverlayRenderer)
ユーザインターフェイスへのMap Viewの追加
MKMapViewクラスは、地図データをアプリケーション上に表示するために必要なインターフェイスを
すべて備えています。地図データの表示、ユーザとの対話操作の管理、アプリケーションによって提
供されたカスタムコンテンツのホスティングが可能です。MKMapViewのサブクラスを定義することは
できません。そのままアプリケーションのビュー階層に埋め込んでください。
また、地図にデリゲートオブジェクトを割り当てる必要もあります。Map Viewは、適切に応答する機
会を得られるように、関連するすべての対話操作をデリゲートに報告します。
Map Viewは、プログラミングによって、あるいはInterface Builderを使用してアプリケーションに追加
できます。
●
●
Interface Builderを使用して地図を追加するには、Map Viewオブジェクトを該当するビューまたは
ウインドウにドラッグします。
プログラミングによって地図を追加するには、MKMapViewクラスのインスタンスを作成し、
initWithFrame:メソッドでこれを初期化してからサブビューとしてウインドウ階層またはビュー
階層へ追加します。
Map Viewはビューであるため、ほかのビューを操作するときと同じ方法でこれを操作できます。たと
えば、ビュー階層内でのサイズと位置の変更、自動サイズ変更動作の設定、サブビューの追加を行う
ことができます。Map View自体は、地図関連のデータの表示、およびそのデータとのすべてのやり取
りを処理する複雑なビュー階層のための不透過(opaque)型のコンテナです。Map Viewに追加したサ
ブビューはすべてframeプロパティによって指定された位置に固定され、地図コンテンツと一緒には
スクロールしません。コンテンツを特定の地図座標に対して相対的に固定(そして地図と一緒にスク
ロール)する必要がある場合は、“地図の注釈” (56 ページ)で説明するように、注釈またはオーバー
レイを使用する必要があります。Map Viewの階層を変更するのは避けた方がよいでしょう。
新しい地図は、ユーザによる対話操作を受け付け、地図データのみを表示するように設定されます。
標準の地図は、デフォルトでは3D透視図になるよう、傾斜を有効にし(すなわち地図に勾配を与え)、
回転を施す(すなわちヘディングを表示する)ようになっています。傾斜や回転は、MKMapCameraオ
ブジェクトを生成することにより指定します。衛星画像、または衛星データと地図データの組み合わ
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
47
地図の表示
地図のプロパティの設定
せを表示するように地図を設定するには、Interface Builderで地図のType属性を変更するか、または
mapTypeプロパティの値を変更します。ユーザによる対話操作を制限したい場合は、rotateEnabled、
pitchEnabled、zoomEnabled、scrollEnabledの各プロパティ値を変更してください。ユーザによ
る対話操作に応答したい場合は、“デリゲートを使ってユーザの操作に応答” (55 ページ)で説明す
るようにデリゲートを使用する必要があります。
地図のプロパティの設定
MKMapViewクラスには、プログラミングによって設定可能なプロパティがいくつかあります。これら
のプロパティは、現在地図のどの部分が表示されているか、内容を3D表示するか、ユーザのどのよう
な対話操作が可能か、といった重要な情報を制御します。
地図の可視部分の設定
MKMapViewクラスのregionプロパティは、地図の現在の可視部分を制御します。地図の可視領域は、
初めて作成された時点では、通常は全世界に設定されます。つまり、表示領域は、地図のできる限り
広い範囲を表示します。この領域は、regionプロパティに新しい値を割り当てることで変更できま
す。このプロパティには、次のような定義を持つMKCoordinateRegion構造体が含まれています。
typedef struct {
CLLocationCoordinate2D center;
MKCoordinateSpan span;
} MKCoordinateRegion;
MKCoordinateRegion構造体の要素のうち、「span」に着目してください。スパンとは、ある点にお
いて可視である地図上の範囲をを表します。矩形の幅と高さの値に似ていますが、地図座標で指定さ
れるため、単位は度、分、秒です。緯度1度は約111キロメートルに相当しますが、経度の長さは緯度
によって変わります。赤道では、経度1度は約111キロメートルに相当しますが、極ではゼロになりま
す。スパンをメートル単位で指定したい場合は、MKCoordinateRegionMakeWithDistanceを使用し
て、度数ではなくメートル値で領域データ構造体を作成します。
regionプロパティに割り当てる値(またはsetRegion:animated:メソッドで設定する値)は通常、
このプロパティによって最終的に保存される値と同じではありません。領域のスパンを設定すると、
表示したい矩形が名目的に定義されるだけでなく、Map View自体の拡大縮小レベルも暗黙的に設定さ
れます。Map Viewは、任意の拡大縮小レベルを表示することができないため、指定された領域を、
Map Viewがサポートする拡大縮小レベルに合うように調節しなければなりません。Map Viewは、でき
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
48
地図の表示
地図のプロパティの設定
る限り画面いっぱいに表示しながら、指定した可視全体を表示できる拡大縮小レベルを選択します。
その後、それに応じてregionプロパティを調節します。regionプロパティの値を実際には変更せず
に結果の領域を確認するには、Map ViewのregionThatFits:メソッドを使用できます。
注意: iOS 7およびOS X v10.9以降、regionおよびvisibleMapRectプロパティは、経度180度
の経線をまたがる領域も参照できるようになりました。このプロパティ値を計算に取り込む
場合、緯度0度、経度180度の点を中心(原点)とした構造体が渡されても、問題が生じない
ようにしてください。
3D地図の表示
3D地図とは、標準的な2D地図を、その面よりも高い位置の、見晴らしがよい点から眺める形で表示
したもののことです。この点の高さと、地図を眺める角度によって、2D地図表面のスパンや勾配(あ
るいは傾斜)が決まります。地図の傾斜や向き(回転)は、ユーザが操作して調整するほか、iOS 7お
よびOS X v10.9以降では、この調整をプログラムで行うことも可能です(MKMapCameraクラスを利
用)。
注意: 地図が3D表示に対応しているかどうか、必ずpitchEnabledプロパティで確認してく
ださい。
カメラオブジェクトは次のプロパティにもとづき、3D地図の外観を定義します。
●
●
高度。地図の表面を基準としたカメラの高さ(メートル単位)。
傾斜。地表面を基準としたカメラの角度(この値が0の場合、垂直に見下ろす形、すなわち標準
2D地図と同じになります)。
●
ヘディング。カメラが基本的に面している方向。
●
中央点。地図表面のうち、画面あるいはウインドウの中央に当たる点。
iOS 7およびOS X v10.9以降、地図は3D表示がデフォルトになりました。これは次のようにアプリケー
ションに影響します。
●
●
地図に傾斜を与えると空が視界に入り、地図の境界の向こう側にある領域も見えるようになりま
す。地図ビューの変換メソッド(convertPoint:toCoordinateFromView:など)の戻り値が有
効かどうか調べて、注釈を空の部分に配置しないよう配慮してください。
Map Kitは、傾斜として無意味な値(たとえば180度。これは天空を見上げることになる)が与え
られると、合理的な値に修正します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
49
地図の表示
地図のプロパティの設定
●
●
3D地図を2次元平面に投影すると、多くの場合、可視領域は矩形でなくなります。このような場
合、傾斜した地図の可視領域を2D近似し、この領域を含む矩形領域をregionプロパティおよび
visibleMapRectプロパティに指定してください。
地図に回転や傾斜を施しても、注釈は自動的に大きさや向きを保とうとするので、アートワーク
がゆがんだり、大きさが変わったりすることはありません(注釈の取り扱いについて詳しくは、
“地図の注釈” (56 ページ)を参照)。
3D地図はiOSでもOS Xでもほとんど同じように動作します。若干の違いは主として、ユーザインター
フェイスおよび基盤となるオブジェクトの種類にもとづくものです。OS Xアプリケーションの場合、
方位磁石、拡大縮小コントロール、地図データの属性ラベルが表示されますが、iOSアプリケーショ
ンにはこれがありません。OS Xの場合、Map Kitには、NSViewおよびNSImageの子孫オブジェクトが定
義されています。iOSにもよく似たオブジェクトがありますが、これはUIViewおよびUIImageの子孫
です。
iOS 7およびOS X v10.9以降、MKMapViewクラスにはcameraプロパティが追加されました。これを使っ
て、3D地図を生成/アクセスし、地図の状態を保存/復元し、拡大縮小やパンの処理コードを記述する
ことができます。たとえばある場所の3D地図は、視点の位置と高さを指定し、Map Kitの機能を使っ
て適切なカメラオブジェクトを生成し、これをMap Viewのcameraプロパティに与えることにより、
容易に生成できます。リスト 5-1にその方法を示します。
リスト 5-1
3D地図の生成
// Create a coordinate structure for the location.
CLLocationCoordinate2D ground = CLLocationCoordinate2DMake(myLatitude, myLongitude);
// Create a coordinate structure for the point on the ground from which to view
the location.
CLLocationCoordinate2D eye = CLLocationCoordinate2DMake(eyeLatitude, eyeLongitude);
// Ask Map Kit for a camera that looks at the location from an altitude of 100
meters above the eye coordinates.
MKMapCamera *myCamera = [MKMapCamera cameraLookingAtCenterCoordinate:ground
fromEyeCoordinate:eye eyeAltitude:100];
// Assign the camera to your map view.
mapView.camera = myCamera;
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
50
地図の表示
地図のプロパティの設定
地図の外観はカメラオブジェクトによって完全に決まるので、地図の状態を保存/復元するためにも
これを利用するとよいでしょう。MKMapCameraクラスはNSSecureCodingプロトコルに準拠している
ので、カメラオブジェクトはアーカイバ(iOSアプリケーションの場合はUIKitの状態復元API)で操作
できます。リスト 5-2に、地図の状態を保存/復元するコード例を示します。
リスト 5-2
地図のアーカイブ保存と復元
MKMapCamera *camera = [map camera]; // Get the map's current camera.
[NSKeyedArchiver archiveRootObject:camera toFile:stateFile]; // Archive the camera.
…
MKMapCamera *camera = [NSKeyedUnarchiver unarchiveObjectWithFile:stateFile]; //
Unarchive the camera.
[map setCamera:camera]; // Restore the map.
地図コンテンツの拡大縮小とパン
拡大縮小とパンによって、地図の可視部分をいつでも変更することができます。
●
●
地図を(拡大縮小レベル、傾斜、回転方向を維持したまま)パンするには、Map Viewまたはカメ
ラのcenterCoordinateプロパティの値を変更するか、またはMap Viewの
setCenterCoordinate:animated:メソッド、あるいはsetCamera:animated:メソッドを使いま
す。
拡大縮小レベルを変更する(さらに必要に応じて地図をパンする)には、Map Viewのregionプロ
パティの値を変更するか、またはsetRegion:animated:メソッドを呼び出します。3D地図では
カメラの高さも変更できます(高さを半分/2倍にすれば、拡大縮小レベルを1段階上げる/下げる
のとほぼ同じ効果が得られます)。
地図のパンだけを行う場合は、centerCoordinateプロパティを変更する方法でのみ行ってくださ
い。regionプロパティを変更することで地図をパンしようとすると、通常は拡大縮小レベルも変わ
ります。これは、領域の一部が変更されると、Map Viewはその領域を適切に表示するために必要な拡
大縮小レベルを評価するためです。現在の緯度を変更すると、ほとんどの場合拡大縮小レベルが変更
され、さらにその他の変更によって異なる拡大縮小レベルが選択されることもあります。
centerCoordinateプロパティ(またはsetCenterCoordinate:animated:メソッド)を使用すると、
Map Viewは拡大縮小レベルを変更せずに、必要に応じてスパンを更新します。たとえば次のコード
は、現在の地図の幅の半分だけ地図を左にパンするために、地図の左端の座標を検出し、それを新し
い中心点として使用します。
CLLocationCoordinate2D mapCenter = myMapView.centerCoordinate;
mapCenter = [myMapView convertPoint:
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
51
地図の表示
地図のプロパティの設定
CGPointMake(1, (myMapView.frame.size.height/2.0))
toCoordinateFromView:myMapView];
[myMapView setCenterCoordinate:mapCenter animated:YES];
地図を拡大縮小するには、表示されている地図の領域のスパンを変更します。拡大するには、スパン
に小さな値を割り当てます。縮小するには、大きな値を割り当てます。たとえば次のように、現在の
スパンが1度の場合、スパンを2度にすると2分の1に縮小されます。
MKCoordinateRegion theRegion = myMapView.region;
// Zoom out
theRegion.span.longitudeDelta *= 2.0;
theRegion.span.latitudeDelta *= 2.0;
[myMapView setRegion:theRegion animated:YES];
地図上でのユーザの現在位置の表示
Map Kitには、ユーザの現在位置を地図上に表示する機能が組み込まれています。この位置を表示する
には、Map ViewオブジェクトのshowsUserLocationプロパティをYESに設定します。これによって、
Map ViewはCore Locationを使用してユーザの現在位置を検出し、MKUserLocation型の注釈を地図に
追加します。
MKUserLocation注釈オブジェクトが地図に追加されると、カスタム注釈が追加されたときと同様に
デリゲートによってそのことが報告されます。カスタム注釈ビューをユーザの位置に関連付けたい場
合は、デリゲートオブジェクトのmapView:viewForAnnotation:メソッドからそのビューを返す必要
があります。デフォルトの注釈ビューを使用する場合は、このメソッドからはnilを返す必要があり
ます。地図に注釈を追加する手順について詳しくは、“地図の注釈” (56 ページ)を参照してくださ
い。
地図のスナップショット作成
対話機能完備のMap Viewをアプリケーションに組み込んでも意味がない場合があります。たとえば、
地図画像をリスト表示し、スクロールしながら選択できるようにする場合、対話機能は不要であるば
かりでなく、スクロール処理がもたつく原因にもなりえます。印刷機能を実装する場合も、静的画像
として地図を生成するとよいでしょう。いずれの場合も、MKMapSnapshotterオブジェクトを使って
非同期に、静的な地図画像を生成できます。この方法で得られるスナップショットには画像ビューが
含まれますが、これに対しては、一般の画像と同様の効果を何でも適用できます。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
52
地図の表示
地図のプロパティの設定
注意: 地図のスナップショットをrenderInContext:で生成しているならば、代わりに
MKMapSnapshotterというAPIを使うよう変更してください。
地図のスナップショットを生成する一般的な手順は次のとおりです。
1.
ネットワークに接続していること、フォアグラウンド状態であることを確認する。
2.
MKMapSnapshotOptionsオブジェクトを生成し、地図の外観、出力の大きさなどを設定する(iOS
アプリケーションの場合、出力の拡大率も指定可)。
3.
MKMapSnapshotterオブジェクトを生成し、手順1で指定したオプションを渡して初期化する。
4.
startWithCompletionHandler:メソッドで、非同期のスナップショット生成タスクを起動する。
5.
タスク終了後、完了ハンドラのブロックから地図のスナップショットを取得し、オーバーレイや
注釈を描画して最終的な画像に仕上げる。
注意: スナップショットの生成に失敗した場合に備えて、プレースホルダ画像を表示するな
どの処理を組み込んでください。
iOSアプリケーションの場合、drawContentForPageAtIndex:inRect:を使って印刷処理を実装する
ことが多いでしょう。このメソッドは、印刷可能な状態のコンテンツを同期的に受け取るものと想定
しているので、スナップショット生成の手順を修正しなければなりません。ディスパッチセマフォと
キューを使って、生成完了時に実行する処理ブロックを管理するのです(ディスパッチセマフォや
キューについては“Using Dispatch Semaphores to Regulate the Use of Finite Resources” in Concurrency
Programming Guide を参照)。
地図の印刷に用いるスナップショットを生成するには(iOSアプリケーションの場合):
1.
MKMapSnapshotOptionsオブジェクトを生成し、必要な設定を施す(プリンタの多くは高精細な
ので、iOSアプリケーションは一般に、拡大率として2倍を指定することに注意)。
2.
MKMapSnapshotterオブジェクトを生成し、手順1で指定したオプションを渡して初期化する。
3.
ディスパッチセマフォを生成して、リソース(この場合はスナップショット)の準備が整うまで
待機できるようにする。
4.
スナップショットの準備が整ったときに呼び出されるコールバックの、登録先ディスパッチキュー
を選択する。
5.
スナップショット生成タスクの結果を保持する変数を生成する。
6.
startWithQueue:completionHandler:を呼び出して、非同期にスナップショットを生成する処
理を起動する。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
53
地図の表示
地図のプロパティの設定
7.
タスク完了後、スナップショット画像をdrawContentForPageAtIndex:inRect:に渡して印刷す
る。
リスト 5-3に、スナップショット印刷処理の実装例を示します。ただしMKMapSnapshotOptionsオブ
ジェクトの生成処理は省略しています。
リスト 5-3
地図の印刷に用いるスナップショットの生成
// Initialize the semaphore to 0 because there are no resources yet.
dispatch_semaphore_t snapshotSem = dispatch_semaphore_create(0);
// Get a global queue (it doesn't matter which one).
dispatch_queue_t queue = dispatch_get_global_queue(myQueuePriorityLevel, 0);
// Create variables to hold return values. Use the __block modifier because these
variables will be modified inside a block.
__block MKMapSnapshot *mapSnapshot = nil;
__block NSError *error = nil;
// Start the asynchronous snapshot-creation task.
[snapshotter startWithQueue:queue
completionHandler:^(MKMapSnapshot *snapshot, NSError *e) {
mapSnapshot = snapshot;
error = e;
// The dispatch_semaphore_signal function tells the semaphore that the async
task is finished, which unblocks the main thread.
dispatch_semaphore_signal(snapshotSem);
}];
// On the main thread, use dispatch_semaphore_wait to wait for the snapshot task
to complete.
dispatch_semaphore_wait(snapshotSem, DISPATCH_TIME_FOREVER);
if (error) { // Handle error. }
// Get the image from the newly created snapshot.
UIImage *image = mapSnapshot.image;
// Optionally, draw annotations on the image before displaying it.
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
54
地図の表示
デリゲートを使ってユーザの操作に応答
デリゲートを使ってユーザの操作に応答
MKMapViewクラスは、地図関連の重要なイベントを対応するデリゲートオブジェクトに報告します。
デリゲートオブジェクトは、MKMapViewDelegateプロトコルに準拠したオブジェクトです。デリゲー
トオブジェクトを使えば、次のようなイベントに応答できます。
●
地図の可視領域の変更
●
ネットワークからの地図タイルの読み込み
●
ユーザの位置の変更
●
注釈とオーバーレイに関連する変更
注釈とオーバーレイに関連する変更への対処についての詳細は、“地図の注釈” (56 ページ)を参照
してください。
「マップ(Maps)」アプリケーションの起動
ユーザ独自のアプリケーションに対して「マップ(Maps)」アプリケーションの地図情報を表示する場
合は、次の2つの手法のいずれかを使用して「マップ(Maps)」をプログラムから起動できます。
●
●
iOS 6およびOS X v10.9以降の場合は、MKMapItemオブジェクトを使用して「マップ(Maps)」を開き
ます。
iOS 5以前の場合は、『Apple URL Scheme Reference 』で説明されている方法に従って特別にフォー
マットされた地図URLを作成して開きます。
「マップ(Maps)」アプリケーションを開くために推奨される方法は、MKMapItemクラスを使用する方
法です。このクラスでは、アプリケーションを開いて位置情報と道順を表示するために、
openMapsWithItems:launchOptions:クラスメソッドとopenInMapsWithLaunchOptions:インスタ
ンスメソッドの両方をサポートしています。
「マップ(Maps)」アプリケーションを開く例としては、“「マップ(Maps)」アプリケーションに道順を
表示するよう要求する” (81 ページ)を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
55
地図の注釈
注釈は、単一の座標点で定義できるコンテンツを表示します。これに対してオーバーレイは、任意の
数の点で定義されるコンテンツを表示し、連続または非連続の1つ以上の図形を構成できます。たと
えば、注釈を使用してユーザの現在位置、特定の住所、関心のある場所などの情報を表示します。
オーバーレイは、経路情報、交通情報のような複雑な情報や、公園、湖、市区町村、州、県、国な
ど、境界線のある領域の表示に使用します。
汎用のサブビューと違い、注釈もオーバーレイも地図上の特定の位置に固定であり、拡大縮小、パ
ン、スクロールに伴って適切に表示位置が変わります。3D地図の場合、回転や傾斜を施しても、注釈
の位置や大きさ、向きは変わりません。
Map Kitは、注釈やオーバーレイに関連付けられているデータと、地図上でのその可視表現を切り離し
ています。切り離すことで、地図は、表示される注釈とオーバーレイを非常に効率良く管理できま
す。つまり何百もの注釈とオーバーレイを地図に追加しても、適切なパフォーマンスを期待できると
いうことです。
地図への注釈の追加
注釈は、地図上で特定の座標位置を目立たせ、その位置に関する追加情報を提供する手段です。注釈
を使用して、特定の住所、関心のある場所、その他さまざまな目的地を吹き出しで示すことができま
す。地図上に表示されるときには、注釈には通常、その位置を示す何らかの画像が付き、情報やより
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
56
地図の注釈
地図への注釈の追加
詳しい内容を表示するリンクを含んだ注釈用吹き出しが付くこともあります。図 6-1に注釈の例を示
します。標準的なピン型の注釈ビューを使ってある場所に印をつけ、吹き出しに追加情報を表示して
います。さらに、詳細表示用のインジケータもついています。
図 6-1
地図での注釈の表示
地図に注釈を表示するには、アプリケーションは2つのオブジェクトを指定する必要があります。
●
●
注釈オブジェクト。MKAnnotationプロトコルに準拠し、注釈のデータを管理するオブジェクト。
注釈ビュー。地図の表面に注釈の可視表現を描画する(MKAnnotationViewクラスから派生した)
ビュー。
注釈オブジェクトは通常、地図座標と注釈に関連するその他の情報(タイトル文字列など)が格納さ
れた比較的小さいデータオブジェクトです。注釈はプロトコルを使用して定義されるため、アプリ
ケーション内のどのクラスも注釈オブジェクトになり得ます。実際には、大量の注釈を地図に追加す
る予定の場合には特に、注釈オブジェクトは軽量に保つことが推奨されます。Map Viewは、追加され
た注釈オブジェクトの参照を保持しており、注釈オブジェクト内のデータを使用して、対応する注釈
ビューをいつ表示すべきかを判断します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
57
地図の注釈
地図への注釈の追加
Map Kitは、ピン型の注釈など、標準的な注釈ビューをいくつか提供しています。また、カスタムの注
釈ビューを定義することもできます。どちらの注釈ビューも、地図の表面に直接追加することはでき
ません。代わりに地図のデリゲートが、地図ビューからの要請に応じて注釈ビューを提供するように
なっています。地図ビューは注釈を、自身のビュー階層に組み入れます。
作成した注釈は通常、不変の単一の地図座標位置に固定されますが、必要ならばその座標をプログラ
ムで変更できます。さらに、ユーザが注釈を、地図のまわりにドラッグできるよう実装することも可
能です。
注釈を地図に追加する手順
以下に、地図を利用するアプリケーションで注釈を実装して使用するための手順を示します。この手
順は、アプリケーションのインターフェイスのどこかに、MKMapViewオブジェクトが組み込まれてい
ることを前提としています。
1.
次のいずれかの方法で、適切な注釈オブジェクトを定義します。
●
MKPointAnnotationクラスを使用して、シンプルな注釈を実装する。このタイプの注釈は、
注釈用吹き出しに表示されるタイトルとサブタイトルの文字列を指定するプロパティを格納
します。
●
MKAnnotation「カスタム注釈オブジェクトの定義」“カスタム注釈オブジェクトの定
義” (59 ページ)プロトコルに準拠したカスタムオブジェクトを定義する。カスタム注釈
は、任意の種類のデータを格納できます。
2.
画面上に注釈データを表示するための注釈ビューを定義します。注釈ビューをどのように定義す
るかは、アプリケーションのニーズに応じて次のいずれかが考えられます。
●
●
●
3.
標準的なピン留めの注釈を使用する場合は、MKPinAnnotationViewクラスのインスタンスを
作成する(“標準注釈ビューの使用” (61 ページ)参照)。
注釈を独自の静止画像で表現できる場合は、MKAnnotationViewクラスのインスタンスを作
成し、そのimageプロパティに対象画像を割り当てる(“標準注釈ビューの使用” (61 ペー
ジ)を参照)。
静止画像だけでは注釈を十分に表現できない場合は、MKAnnotationViewをサブクラス化し、
これを表現するために必要なカスタム描画コードを実装する。カスタム注釈ビューを実装す
る方法については、“カスタム注釈ビューの定義” (61 ページ)を参照。
Map ViewデリゲートにmapView:viewForAnnotation:メソッドを実装します。
このメソッドの実装では、既存の注釈ビューがあればそれをキューから取り出し、なければ新規
に作成します。アプリケーションで複数種類の注釈をサポートする場合は、提供する注釈オブ
ジェクトに適したタイプのビューを作成するロジックをメソッドに追加します。
mapView:viewForAnnotation:メソッドの実装について詳しくは、“デリゲートオブジェクトか
らの注釈ビューの作成” (63 ページ)を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
58
地図の注釈
地図への注釈の追加
addAnnotation:(またはaddAnnotations:)メソッドを使用して、Map Viewに注釈オブジェク
4.
トを追加します。
Map Viewに注釈を追加すると、Map Viewは、表示された地図矩形内にその注釈の座標があれば、対応
する注釈ビューが表示されます。特定の注釈を非表示にするには、デベロッパ自身がMap Viewから注
釈を手動で削除する必要があります。注釈の追加と削除はいつでも行うことができます。
注釈はすべて、地図の現在の拡大縮小レベルに関係なく、毎回同じ縮尺で描画されます。そのため、
地図に多数の注釈が含まれていると、ユーザが地図を縮小したときに注釈ビューが重なり合う可能性
があります。この動作に対処するために、地図の現在の拡大縮小レベルに応じて注釈の追加と削除を
行うことができます。たとえば、天気情報アプリケーションであれば、地図が州や県全体を表示する
ように縮小されたときには、主要都市の情報のみ表示するなどが考えられます。ユーザが表示を拡大
したときには、アプリケーションは、より小さな市や地域の天気情報を示す新しい注釈を追加するこ
とができます。注釈の追加と削除に必要なロジックを実装するのは、デベロッパの責任です。
Map Viewの注釈の効果的な管理方法の詳細については、“複数の注釈オブジェクトの表示” (68 ペー
ジ)を参照してください。
カスタム注釈オブジェクトの定義
タイトルと地図座標を関連付けるだけであれば、MKPointAnnotationクラスを注釈オブジェクトに
使用できます。しかし、その他の情報を注釈に表示するためには、カスタムの注釈オブジェクトを定
義する必要があります。注釈オブジェクトはすべて、MKAnnotationプロトコルに従わなければなり
ません。
カスタムの注釈オブジェクトは、地図座標および注釈に関連付ける必要のあるその他のデータから成
ります。リスト 6-1に、カスタム注釈クラスを宣言するために最小限必要となるコードを示します。
coordinateプロパティの宣言は、MKAnnotationプロトコルからのもので、すべての注釈クラスに含
める必要があります。これは単純な注釈であるため初期化メソッドも含まれており、これを使用し
て、読み取り専用のcoordinateプロパティに値を設定しています。アプリケーションの宣言には、
さらに追加の注釈データを定義するメソッドとプロパティを含めることになります。
リスト 6-1
シンプルな注釈オブジェクトの作成
@interface MyCustomAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
}
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithLocation:(CLLocationCoordinate2D)coord;
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
59
地図の注釈
地図への注釈の追加
// Other methods and properties.
@end
カスタムクラスには、座標プロパティと、そのプロパティ値の設定方法を実装する必要があります
(@synthesize構文でcoordinateの設定/取得メソッドを生成するよう推奨。こうしておけば、Map Kit
が自動的に、プロパティの変更に応じて地図を更新できます)。あとは、リスト 6-2に示すように、
カスタムのinitWithLocation:メソッドを実装するだけです。
リスト 6-2
MyCustomAnnotationクラスの実装
@implementation MyCustomAnnotation
@synthesize coordinate;
- (id)initWithLocation:(CLLocationCoordinate2D)coord {
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
@end
Important: このプロパティのメソッドを自分で実装する場合、または地図への注釈の追加後にク
ラスの別の部分にあるプロパティ内の変数を手動で修正する場合は、これを実行する際に通知を
送信する必要があります。Map Kitではキー値監視(KVO)通知を使用して、coordinate、title、
およびsubtitleの各プロパティに対する注釈の変更を検出し、地図の表示で必要な変更を行いま
す。KVO通知を送信しないと、注釈の位置が地図上で適切に更新されない場合があります。
KVOに準拠したアクセサメソッドを実装する方法については、『Key-Value Observing Programming
Guide 』を参照してください。
注釈オブジェクトの例は、サンプルコードプロジェクト『MapCallouts 』を参照してください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
60
地図の注釈
地図への注釈の追加
標準注釈ビューの使用
標準注釈ビューを使えば、容易に地図上に注釈を表示できます。MKAnnotationViewクラスには、あ
らゆる注釈ビューに共通の、基本的な動作が定義されています。たとえば、MKPinAnnotationView
はMKAnnotationViewのサブクラスで、標準のシステムピン画像の1つを、対応する注釈の座標点に
表示します。MKAnnotationViewを使って、サブクラスを定義することなく、独自に用意したカスタ
ム静止画像を表示することも可能です。
カスタム画像を注釈として表示するためには、MKAnnotationViewのインスタンスを生成し、その
imageプロパティに画像を設定してください。注釈を表示すると、この画像が、対象の地図座標を中
心において表示されます。地図座標を中心において画像を配置したくない場合は、centerOffsetプ
ロパティを使用して、中心点を縦横の任意の方向に移動できます。リスト 6-3に、注釈座標から右上
にずれた位置にカスタム画像を表示する、注釈ビューの作成例を示します。
リスト 6-3
カスタム画像を指定した標準注釈ビューの作成
MKAnnotationView* aView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:@"MyCustomAnnotation"];
aView.image = [UIImage imageNamed:@"myimage.png"];
aView.centerOffset = CGPointMake(10, -20);
標準的な注釈ビューは、デリゲートのmapView:viewForAnnotation:メソッドで作成します。このメ
ソッドの実装方法の詳細については、“デリゲートオブジェクトからの注釈ビューの作成” (63 ペー
ジ)を参照してください。
カスタム注釈ビューの定義
静止画像だけでは注釈を十分に表現できない場合は、次のいずれかの方法で、MKAnnotationViewを
サブクラス化して動的にコンテンツを描画します。
●
●
この場合もやはりMKAnnotationViewのimageプロパティを使いますが、定期的に画像を差し替
えます。
注釈ビューのdrawRect:メソッドをオーバーライドして、コンテンツを毎回、動的に描画するよ
う実装します。
ビューで行うほかのカスタム描画の場合と同様に、アプローチを決める前に必ずパフォーマンスを考
慮してください。カスタム描画は柔軟性は優れていますが、コンテンツのほとんどが一定のままであ
れば特に、画像を使用したほうが速くなる可能性があります。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
61
地図の注釈
地図への注釈の追加
drawRect:メソッドでコンテンツを描画する場合、初期化の後すぐに、注釈ビューに対してゼロ以外
のフレームサイズを指定して、描画したコンテンツが可視になるようにしなければなりません。これ
が必要なのは、注釈ビューのデフォルトの初期化メソッドが、imageプロパティに指定された画像を
使って、後からフレームサイズを設定するからです。このプロパティを設定せず、別途画像を描画す
る場合、ビューのframeプロパティを明示的に設定しなければ、描画の結果が可視になりません。さ
らに、ビューが描画するのはフレーム部分のみなので、opaqueプロパティをNOと設定して、残りの
地図コンテンツが透けて見えるようにします。opaqueプロパティを設定しないと、描画システムは
現在の背景色でビューを塗りつぶしてからdrawRect:メソッドを呼び出します。リスト 6-4に、カス
タム注釈ビューのフレームサイズと不透明度を設定する、初期化メソッドの例を示します。
リスト 6-4
カスタム注釈ビューの初期化
- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString
*)reuseIdentifier
{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self)
{
// Set the frame size to the appropriate values.
CGRect
myFrame = self.frame;
myFrame.size.width = 40;
myFrame.size.height = 40;
self.frame = myFrame;
// The opaque property is YES by default. Setting it to
// NO allows map content to show through any unrendered parts of your view.
self.opaque = NO;
}
return self;
}
その他多くの点で、注釈ビューでのカスタムコンテンツの描画は、ほかのビューの場合と同じです。
システムはビューのdrawRect:メソッドを呼び出し、ビューのうち再描画が必要な部分を再描画しま
すが、ビューのsetNeedsDisplayメソッドまたはsetNeedsDisplayInRect:メソッドを呼び出してい
つでも強制的に再描画を行うこともできます。ビューのコンテンツをアニメーション化する場合は、
一定間隔で作動するタイマーを設定してビューを更新します。タイマーの設定方法については、『Timer
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
62
地図の注釈
地図への注釈の追加
Programming Topics 』を参照してください。また、ビューがコンテンツを描画する仕組みの詳細につ
いては、『View Programming Guide for iOS 』または『Cocoa Drawing Guide 』(OS Xの場合)を参照し
てください。
デリゲートオブジェクトからの注釈ビューの作成
注釈ビューが必要になると、Map ViewはそのデリゲートオブジェクトのmapView:viewForAnnotation:
メソッドを呼び出します。このメソッドを実装していない場合、または実装していて常にnilが返さ
れる場合、Map Viewはデフォルトの注釈ビュー(通常はピン注釈ビュー)を使用します。デフォルト
以外の注釈ビューが返されるようにするには、mapView:viewForAnnotation:メソッドをオーバーラ
イドして、使用するビューをそこで作成する必要があります。
mapView:viewForAnnotation:メソッドで新しいビューを作成する前に、必ず、既存の類似の注釈
ビューがないか確認してください。Map Viewには、使用されていない注釈ビューがあればそれをキャッ
シュに入れるという選択肢があるので、dequeueReusableAnnotationViewWithIdentifier:メソッ
ドを実行したとき、未使用のビューが得られることもありえます。キューからの取り出しメソッドが
nil以外の値を返した場合、ビューの属性を更新してこれを返します。nilを返した場合は、適切な
注釈ビュークラスのインスタンスを生成して返します。どちらの場合も、このメソッドに渡された注
釈を受け取り、それを注釈ビューに割り当てるのはデベロッパの責任です。また、
mapView:viewForAnnotation:を使って、ビューを返す前に更新しておく必要があります。
リスト 6-5に、mapView:viewForAnnotation:メソッドの実装例を示します。カスタム注釈オブジェ
クトに対応してピン注釈ビューを返すようになっています。既存のピン注釈ビューがすでに存在する
場合、このメソッドは注釈オブジェクトをそのビューに関連付けます。再利用キューにビューが存在
しない場合、このメソッドは新しいビューを作成し、基本的なプロパティを設定します。地図が現
在、ユーザの位置を示していれば、このメソッドはすべてのMKUserLocationオブジェクトについて
nilを返し、デフォルトの注釈ビューが使用されるようにします(さらに、
mapView:viewForAnnotation:メソッドで吹き出しをカスタマイズすることも可能です。“吹き出し
の作成” (64 ページ)を参照)。
リスト 6-5
注釈ビューの作成
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation
{
// If the annotation is the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
63
地図の注釈
地図への注釈の追加
if ([annotation isKindOfClass:[MyCustomAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKPinAnnotationView*
pinView = (MKPinAnnotationView*)[mapView
dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:@"CustomPinAnnotationView"];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
// If appropriate, customize the callout by adding accessory views
(code not shown).
}
else
pinView.annotation = annotation;
return pinView;
}
return nil;
}
吹き出しの作成
吹き出しは、標準ビューまたはカスタムビューの一種で、注釈ビューから引き出される形で表示する
ようになっています。標準の吹き出しには、注釈のタイトルに加え、サブタイトル、画像、コント
ロール部品などを表示することも可能です。吹き出しのように振る舞うカスタムビューを表示するた
めには、カスタムサブビューを注釈ビューに追加し、注釈ビューのヒットテスト用メソッドをオー
バーライドして、ユーザとサブビューとのやり取りを処理できるようにしてください。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
64
地図の注釈
地図への注釈の追加
カスタムサブビューを生成することなくカスタムコンテンツを表示する方法としては、標準の吹き出
しを利用するのが最も簡単でしょう。図 6-2に、標準の吹き出しに手を加えて、カスタム画像および
詳細開示ボタンを表示するようにした例を示します(リスト 6-6はこの吹き出しを生成するコード)。
図 6-2
標準の吹き出しにカスタム画像および詳細開示ボタンを表示している様子
リスト 6-6
標準の吹き出しのカスタマイズ
// This code snippet assumes that an annotation for the Golden Gate Bridge has
already been added to the map view.
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id
<MKAnnotation>)annotation
{
// Try to dequeue an existing pin view first (code not shown).
// If no pin view already exists, create a new one.
MKPinAnnotationView *customPinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:BridgeAnnotationIdentifier];
customPinView.pinColor = MKPinAnnotationColorPurple;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
65
地図の注釈
地図への注釈の追加
// Because this is an iOS app, add the detail disclosure button to display details
about the annotation in another view.
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:nil action:nil forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
// Add a custom image to the left side of the callout.
UIImageView *myCustomImage = [[UIImageView alloc] initWithImage:[UIImage
imageNamed:@"MyCustomImage.png"]];
customPinView.leftCalloutAccessoryView = myCustomImage;
return customPinView;
}
iOSアプリケーションの場合、ユーザが吹き出しビューのコントロール部品をタップしたとき、
mapView:annotationView:calloutAccessoryControlTapped:デリゲートメソッドを使って応答す
るように実装するとよいでしょう(コントロール部品がUIControlの子孫クラスである場合)。この
メソッドでは、吹き出しビューに対応する注釈ビューのIDを取得することにより、どの注釈がタップ
されたか判断できます。Macアプリケーションの場合、吹き出しビューのビューコントローラにアク
ションメソッドを実装して、ユーザがコントロール部品をクリックしたときに応答できるようにして
ください。
標準の吹き出しの代わりにカスタムビューを使う場合、ユーザの操作に応じて適切に吹き出しの表示/
非表示が切り替わるよう、コードを追加しなければなりません。ボタンつきの吹き出しを生成する手
順の概要を以下に示します。
1.
カスタムの吹き出しを表示する、NSViewまたはUIViewのサブクラスを設計する。ここにはおそ
らく、カスタムコンテンツを描画する、drawRect:メソッドを実装する必要があるでしょう。
2.
吹き出しビューを初期化し、ボタン操作に応じたアクションを実行する、ビューコントローラを
生成する。
3.
注釈ビューにhitTest:メソッドを実装して、注釈ビューの境界外、かつ吹き出しビューの境界内
に当たる位置でヒットしたとき、応答できるようにする(リスト 6-7 (67 ページ)を参照)。
4.
注釈ビューにsetSelected:animated:メソッドを実装して、ユーザがクリック/タップしたとき、
吹き出しビューを注釈ビューのサブビューとして追加するようにする。吹き出しビューをユーザ
が選択したとき、既に可視であれば、setSelected:メソッド内で、吹き出しサブビューを注釈
ビューから除去しなければなりません(リスト 6-8 (67 ページ)を参照)。
5.
注釈ビューのinitWithAnnotation:メソッドで、canShowCalloutプロパティをNOにすることに
より、ユーザが注釈を選択しても、地図に標準の吹き出しが表示されないようにする。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
66
地図の注釈
地図への注釈の追加
リスト 6-7にhitTest:メソッドの実装例を示します。吹き出しビュー内(おそらく注釈ビューの境界
外)でのヒットを処理するメソッドです。
リスト 6-7
カスタムの吹き出し内でのヒットに応答
- (NSView *)hitTest:(NSPoint)point
{
NSView *hitView = [super hitTest:point];
if (hitView == nil && self.selected) {
NSPoint pointInAnnotationView = [self.superview convertPoint:point
toView:self];
NSView *calloutView = self.calloutViewController.view;
hitView = [calloutView hitTest:pointInAnnotationView];
}
return hitView;
}
リスト 6-8にsetSelected:animated:メソッドの実装例を示します。ユーザが注釈ビューを選択した
とき、カスタムの吹き出しビューが現れ、あるいは消える様子をアニメーション表示します。
リスト 6-8
カスタムの吹き出しビューを追加/削除
- (void)setSelected:(BOOL)selected
{
[super setSelected:selected];
// Get the custom callout view.
NSView *calloutView = self.calloutViewController.view;
if (selected) {
NSRect annotationViewBounds = self.bounds;
NSRect calloutViewFrame = calloutView.frame;
// Center the callout view above and to the right of the annotation view.
calloutViewFrame.origin.x = -(NSWidth(calloutViewFrame) NSWidth(annotationViewBounds)) * 0.5;
calloutViewFrame.origin.y = -NSHeight(calloutViewFrame) + 15.0;
calloutView.frame = calloutViewFrame;
[self addSubview:calloutView];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
67
地図の注釈
地図への注釈の追加
} else {
[calloutView.animator removeFromSuperview];
}
}
複数の注釈オブジェクトの表示
アプリケーションで多数の注釈を扱う場合は、これをどのように表示するか検討する必要がありま
す。地図ビューは、自分が認識している注釈がすべてアクティブであるとして扱い、特定の座標点が
画面上にあるときには、常に対応する注釈ビューを表示しようとします。これにより、2つの注釈の
座標が近接していると、対応する注釈ビューが重なり合うこともあります。地図に数百もの注釈が含
まれていると、ある程度以上に縮小表示した状態では、注釈ビューが大量に表示されて見栄えが悪く
なります。さらに、注釈が密集しすぎると、ユーザがアクセスできないビューも出てきます。
注釈の過密状態を解消する唯一の方法は、Map Viewから注釈オブジェクトをいくつか取り除くことで
す。このためには通常、mapView:regionWillChangeAnimated:メソッドと
mapView:regionDidChangeAnimated:メソッドを実装して、地図の拡大縮小レベルの変更を検出す
る必要があります。拡大縮小率の変更中に、注釈同士の距離に応じて、必要であれば注釈の追加また
は削除を行うことができます。また、注釈を取り除くその他の基準(ユーザの現在の位置など)を検
討することもできます。
Map Kitには地図上の点と点の近さを簡単に求める関数が多数含まれています。注釈の地図座標を地図
点の座標空間に変換する場合は、MKMetersBetweenMapPointsメソッドを使用して2点間の絶対距離
を取得できます。各座標を地図矩形の中心として使用し、MKMapRectIntersectsRect関数を使用し
て交差部分を求めることもできます。すべての関数の一覧については、『MapKitFunctionsReference 』
を参照してください。
注釈ビューをドラッグ可能として登録する
注釈ビューにはドラッグ機能が組み込まれているので、地図上での注釈のドラッグと、それに応じた
注釈データの更新が非常に簡単にできるようになりました。ドラッグのための最小限のサポートを実
装するには:
●
●
注釈オブジェクト内で、setCoordinate:メソッドを実装してMap Viewが注釈の座標点を更新で
きるようにする。
注釈ビューの作成時に、draggableプロパティをYESに設定する。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
68
地図の注釈
地図へのオーバーレイの表示
ドラッグ可能な注釈ビューをユーザがタッチアンドホールドすると、Map Viewは注釈ビューのドラッ
グ操作を開始します。ドラッグ操作が進行すると、Map Viewはデリゲートの
mapView:annotationView:didChangeDragState:fromOldState:メソッドを呼び出して、ビューの
ドラッグ状態への変更を通知します。このメソッドを使用して、ドラッグ操作に関与したり応答した
りできます。
ドラッグ操作中、ビューをアニメーション表示したい場合は、注釈ビューにdragStateメソッドを実
装してください。Map Viewは、ドラッグ関連のタッチイベントを処理するたびに、影響を受ける注釈
ビューのdragStateプロパティを更新します。カスタムのdragStateメソッドを実装すれば、アプリ
ケーションは、これらの変更を横取りして追加の処理を実行する(ビューの外観をアニメーション化
するなど)機会が得られます。たとえば、MKPinAnnotationViewクラスは、ドラッグ操作が開始す
ると地図上のピンを抜き、ドラッグ操作が終了するとピンを刺します。
地図へのオーバーレイの表示
オーバーレイは、地図上の任意の領域の上にコンテンツを積み重ねる手段を提供します。注釈は常に
1つの地図座標によって定義されるのに対し、オーバーレイは通常は複数の座標によって定義されま
す。これらの座標を使用して、連続または非連続の線、矩形、円、その他の一連の図形を作成し、さ
らに色で塗りつぶしやストロークの処理を施すことができます。たとえば、オーバーレイを使用して
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
69
地図の注釈
地図へのオーバーレイの表示
道路の上に交通情報を重ねたり、公園の区画を目立たせたり、市区町村、州、県、国の境界を示した
りなどが可能です。図 6-3に、コロラド州を覆うオーバーレイの塗りつぶしとストロークを表示しま
す。
図 6-3
地図へのオーバーレイの表示
地図にオーバーレイを表示するには、アプリケーションは2つのオブジェクトを指定する必要があり
ます。
●
●
オーバーレイオブジェクト。MKOverlayプロトコルに準拠し、オーバーレイのデータ点を管理す
るオブジェクト。
オーバーレイレンダラ。地図の表面にオーバーレイの可視表現を描画する(MKOverlayRenderer
クラスから派生する)ビュー。
注意: iOS 7.0以降は、MKOverlayViewの代わりにMKOverlayRendererを使ってください。
レンダラにはビューと同じ機能がありますが、より軽量で、処理効率も向上しています。
オーバーレイオブジェクトは一般に、オーバーレイを定義する点とタイトル文字列などの関連情報が
格納された小さなデータオブジェクトです。オーバーレイはプロトコルを使用して定義されるため、
アプリケーション内のどのクラスもオーバーレイオブジェクトになり得ます。さらに、Map Kitは、各
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
70
地図の注釈
地図へのオーバーレイの表示
種の標準的な図形を指定する具象オーバーレイオブジェクトをいくつか定義しています。Map View
は、追加されたオーバーレイオブジェクトの参照を保持しており、それらのオブジェクト内のデータ
を使用して、対応するビューをいつ表示すべきかを判断します。
Map Kitは、具象オーバーレイオブジェクトによって表現される任意の図形を描画できる、標準的な
オーバーレイレンダラを提供します。注釈と同様、オーバーレイレンダラを地図の表面に直接追加す
ることはできません。代わりにデリゲートオブジェクトが、要請に応じてオーバーレイレンダラを提
供し、Map Viewがオーバーレイを不透過のビュー階層に組み入れるようにします。
通常、オーバーレイの地図上の座標は変わりません。ドラッグ可能なオーバーレイを作成することは
可能ですが、そうすることは稀です。ドラッグ操作の追跡とオーバーレイ座標点の更新を行うコード
を、デベロッパ自身で実装する必要があります。
地図にオーバーレイを追加する手順
以下に、地図を利用するアプリケーションにオーバーレイを実装して使用するための手順を示しま
す。この手順は、アプリケーションのインターフェイスのどこかに、MKMapViewオブジェクトが組み
込まれていることを前提としています。
1.
次のいずれかの方法で、適当なオーバーレイデータオブジェクトを定義します。
●
●
●
MKCircle、MKPolygonクラスまたはMKPolylineクラスをそのまま使います。
カスタムビットマップタイルの集合としてオーバーレイが表されているならば、MKTileOverlay
クラスを使います。
MKShapeまたはMKMultiPointをサブクラス化して、アプリケーション固有の動作を提供する
オーバーレイ、またはカスタムの図形を使用するオーバーレイを作成します。
●
2.
アプリケーションの既存のクラスを利用し、それをMKOverlayプロトコルに適合させます。
次のいずれかの方法で、画面にオーバーレイ表示する、オーバーレイレンダラを定義します。
●
●
●
標準的な図形の場合は、MKCircleRenderer、MKPolygonRenderer、MKPolylineRenderer
のいずれかのクラスで、オーバーレイを描画します。これらのクラスを使って最終的な図形
のさまざまな描画属性をカスタマイズできます。
タイル化オーバーレイの場合、MKTileOverlayRendererクラスを使って、地図上にタイルを
描画します。
MKShapeから派生したカスタムの図形の場合は、MKOverlayPathRendererの適切なサブクラ
スを定義して、図形を描画します。
●
3.
それ以外のカスタムの図形やオーバーレイの場合は、MKOverlayRendererをサブクラス化し
てカスタムの描画コードを実装します。
Map ViewデリゲートにmapView:rendererForOverlay:メソッドを実装します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
71
地図の注釈
地図へのオーバーレイの表示
4.
addOverlay:メソッドやその他のメソッドを使って、Map Viewにオーバーレイデータオブジェク
トを追加します。
注釈とは異なり、描画したオーバーレイは、地図の現在の拡大縮小レベルに合うように、自動的に拡
大縮小されます。オーバーレイは一般的に、区画や道路など、ズーム操作時に拡大縮小するコンテン
ツを強調表示するので、オーバーレイの拡大縮小が必要になります。
地図におけるオーバーレイのZ軸方向の重なりを再配置して、特定のオーバーレイが常に最前面に表
示されるようにすることができます。さらに、他の地図コンテンツ(道路、ラベル、注釈ビューな
ど)との関係でオーバーレイのレベルを指定するためには、MKOverlayLevelに定義されている、次
の定数を使います。
●
MKOverlayLevelAboveRoads
●
MKOverlayLevelAboveLabels
注意: 3D地図で、MKOverlayLevelAboveRoadsレベルを指定したオーバーレイは、3Dの建
物で埋めることができます。この外観は、オーバーレイが地面上にあるように見せたい場合
に適しています。
オーバーレイには、システムが提供する地図の内容を残したまま情報を補足する使い方と、完全に置
き換えてしまう使い方があります。オーバーレイが不透明であれば、その奥にある地図内容は描画し
ても見えないので、システムが不必要なロード/描画処理をしないよう、canReplaceMapContentプ
ロパティを使ってください。
標準のオーバーレイオブジェクトとビューの使用
特定の地図領域を強調表示するだけであれば、標準のオーバーレイクラスを使用するのが最も簡単で
す。標準のオーバーレイクラスとしては、MKCircle、MKPolygon、MKPolylineがあります。これら
のクラスはオーバーレイの基本的な図形を定義し、地図の表面上でこれらの図形の描画を処理するク
ラスMKCircleRenderer、MKPolygonRenderer、MKPolylineRendererと一緒に使用されます。
リスト 6-9に、図 6-3 (70 ページ)に示した矩形のポリゴン(多角形)の作成方法の例を示します。
このポリゴンは、コロラド州の4つの角に対応する4つの地図座標で構成されています。ポリゴンを作
成した後は、addOverlay:メソッドを使用して地図に追加するだけです。
リスト 6-9
ポリゴンのオーバーレイオブジェクトの作成
// Define an overlay that covers Colorado.
CLLocationCoordinate2D
points[4];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
72
地図の注釈
地図へのオーバーレイの表示
points[0] = CLLocationCoordinate2DMake(41.000512, -109.050116);
points[1] = CLLocationCoordinate2DMake(41.002371, -102.052066);
points[2] = CLLocationCoordinate2DMake(36.993076, -102.041981);
points[3] = CLLocationCoordinate2DMake(36.99892, -109.045267);
MKPolygon* poly = [MKPolygon polygonWithCoordinates:points count:4];
poly.title = @"Colorado";
[map addOverlay:poly];
オーバーレイを地図に表示するため、Map ViewデリゲートのmapView:viewForOverlay:メソッドで
用いる、適切なオーバーレイレンダラを用意する必要があります。標準のオーバーレイ図形の場合
は、表示する図形のタイプに合致するビューを作成することで、オーバーレイレンダラを準備できま
す。リスト 6-10に、コロラド州を覆うポリゴンレンダラを作成するようにこのメソッドを実装する例
を示します。この例では、このメソッドは図形とボーダー幅を描画する色を設定しています。
リスト 6-10 図形描画のためのポリゴンレンダラの作成
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id
<MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolygon class]])
{
MKPolygonRenderer*
aRenderer = [[MKPolygonRenderer alloc]
initWithPolygon:(MKPolygon*)overlay];
aRenderer.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
aRenderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
aRenderer.lineWidth = 3;
return aRenderer;
}
return nil;
}
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
73
地図の注釈
地図へのオーバーレイの表示
標準のオーバーレイレンダラは、オーバーレイによって表現される図形の塗りつぶしとストロークを
簡素化します。ほかに情報を表示する場合は、必要な描画を行うカスタムのオーバーレイレンダラを
作成する必要があります。追加のコンテンツをレンダリングするために既存のオーバーレイにサブ
ビューを追加することは避けてください。オーバーレイに追加するサブビューはすべて、オーバーレ
イと一緒に拡大縮小され、地図の拡大縮小レベルに合わせられます。サブビューに含まれているコン
テンツが拡大縮小に適切に対応できるのでない限り、結果の見栄えはあまり良くないことが考えられ
ます。
タイル化オーバーレイの取り扱い
カスタムビットマップタイルを使ってオーバーレイを実装する場合、MKTileOverlayでタイルを管理
し、MKTileOverlayRendererで表示することになります。MKTileOverlayオブジェクトは単独で、
さまざまなズームレベルのタイルを扱えます。このクラスのURLテンプレートを使って、アプリケー
ションバンドルやサーバにおける位置だけでなく、タイルの地図上の位置、ズームレベル、拡大率も
指定できるからです。
デフォルトでは、地図の左上隅が、タイルのx値、y値の原点になります(geometryFlippedプロパ
ティで原点を左下隅に変更できますが、独自の指標づけ方式にしたければ、MKTileOverlayのサブク
ラスを定義する必要があります)。ズームレベルを変えると、タイルの数が2の累乗単位で増減しま
す。たとえばズームレベルが3であれば、x方向、y方向のどちらにも、8枚のタイルが並ぶことになり
ます。
地図の曲がり具合に合致したタイルを生成するには、EPSG:3857の球面メルカトル投影座標系を採用
するとよいでしょう。
カスタムオーバーレイオブジェクトの定義
オーバーレイオブジェクトの役割は、オーバーレイの座標データおよび関連する追加情報を管理する
ことです。Map Kitは、カスタムオーバーレイを定義する、次のような手段を提供しています。
●
アプリケーションで定義済みのいずれかのクラスを、MKOverlayプロトコルに準拠させる方法
●
MKShapeまたはMKMultiPointのサブクラスに、図形ベースのオーバーレイを新たに定義する方法
●
MKTileOverlayのサブクラスを定義し、独自の指標づけ方式でタイルを管理する方法
サブクラスを定義するか、MKOverlayプロトコルに準拠させるかによらず、カスタムオーバーレイオ
ブジェクトに対する作業はほとんど同じです。オーバーレイオブジェクトの主要な役割は、2つの重
要な情報を提供することです。
●
オーバーレイの中心点を定義する座標
●
オーバーレイのコンテンツを完全に囲む境界矩形
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
74
地図の注釈
地図へのオーバーレイの表示
境界矩形はオーバーレイ自身に関する最も重要な情報です。Map Viewは、オーバーレイオブジェクト
によって指定される境界矩形を手がかりに、対応するオーバーレイレンダラをいつ地図に追加するか
を決定します(オーバーレイを注釈としても地図に追加する場合、同様に座標値によって、対応する
注釈ビューをいつ地図に追加すべきかが決まります)。境界矩形自身は、地図座標ではなく、地図点
を使用して指定されます。2つの座標系の間は、Map Kit関数を使用して変換できます。
オーバーレイの表示に伴う実際の作業のほとんとは、対応するオーバーレイレンダラオブジェクトが
責任を負います。オーバーレイオブジェクトは、地図上でオーバーレイを配置する場所を単に定義す
るのに対し、オーバーレイレンダラは、オーバーレイに表示される情報(もしあれば)など、オー
バーレイの最終的な表示内容を定義します。カスタムオーバーレイレンダラの作成については、“カ
スタムオーバーレイレンダラの定義” (75 ページ)で詳しく述べます。
カスタムオーバーレイレンダラの定義
オーバーレイ図形に対して、境界線の描画やコンテンツの塗りつぶし以上の処理を施したい場合は、
カスタムオーバーレイレンダラを作成する必要があります。たとえば、交通情報のオーバーレイを描
画する場合は、カスタムオーバーレイレンダラを使用して、交通状況に基づいて道路を色分けするこ
とができます。また、カスタムの描画コードを使用して、オーバーレイの表示をアニメーション化す
ることもできます。
カスタムのオーバーレイレンダラを作成するには、MKOverlayRendererをサブクラス化します(既
存の図形ベースのオーバーレイの描画動作を単に変更するだけであれば、代わりに
MKOverlayPathRendererをサブクラス化することもできます)。
MKOverlayRendererのカスタムの実装においては、次のメソッドを実装する必要があります。
●
drawMapRect:zoomScale:inContext:。このメソッドはカスタムコンテンツを描画します。
●
canDrawMapRect:zoomScale:。描画コードが、常に利用可能とは限らないコンテンツに依存す
る場合はこのメソッドを使用します。
canDrawMapRect:zoomScale:メソッドは、コンテンツが必ずしも描画する準備ができているとは限
らない状況で使用します。たとえば、交通情報オーバーレイであれば、描画する前に、必要な交通
データをネットワークからダウンロードする必要があります。このメソッドからNOを返されると、
Map Viewは、アプリケーション側から準備ができたことを知らされるまでオーバーレイの描画を行い
ません。準備ができたことを知らせるには、setNeedsDisplayInMapRect:メソッドまたは
setNeedsDisplayInMapRect:zoomScale:メソッドのどちらかを使用して、ビューをダーティとして
マークします。
ビューの描画の準備ができたら、Map ViewはdrawMapRect:zoomScale:inContext:メソッドを呼び
出して実際の描画を行います(なお、タイルを描画しながら画像処理を行う必要があれば、
MKTileOverlayRendererのサブクラスを定義してください)。標準のビューへの描画とは異なり、
オーバーレイビュへの描画では、いくつか特別な配慮が必要です。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
75
地図の注釈
地図へのオーバーレイの表示
描画コードは、ビューの境界やフレームを、描画の基準点として使用することはできません。代
わりに、オーバーレイオブジェクトに関連付けられている地図点を使用して図形を定義してくだ
さい。描画コードは、MKOverlayRendererクラスの変換ルーチンを使用して、描画の直前にこれ
らの地図点を点(CGPointなど)に変換する必要があります。
●
また、このメソッドに渡された拡大縮小の尺度値は、通常は直接コンテンツには適用しません。
この値は、Map Kit関数またはメソッドが特別に必要とする場合に限り指定します。地図点を使用
してコンテンツを指定し、それを点に変換する限り、コンテンツは自動的に正しいサイズに拡大
縮小されるはずです。
●
UIKitのクラスと関数を使用して描画する場合は、描画環境の設定と後処理を明示的に行う必要が
あります。呼び出しに先立ち、UIGraphicsPushContext関数を呼び出して、メソッドに渡され
たコンテキストをカレントコンテキストにします。描画を終えたら、UIGraphicsPopContextを
呼び出してコンテキストを削除します。
●
Map Viewは大きなオーバーレイをタイル表示して、各タイルを別々のスレッドでレンダリングで
きる点に留意してください。そのため、描画コードは、変数やその他のデータをスレッドセーフ
な方法で変更することができない限り、変更しようとしてはなりません。
リスト 6-11に、オーバーレイの境界矩形をグラデーションを使って塗りつぶす描画コードを示しま
す。グラデーションを描画する際は、対象の描画領域にクリッピング矩形を適用することによって、
この描画処理を封じ込めることが特に重要です。ビューのフレームはオーバーレイの境界矩形よりも
実際には大きいため、クリッピング矩形が適用されなければ、グラデーションは想定している領域の
範囲を超えてレンダリングされるためです。オーバーレイの境界矩形は、この場合は実際の図形を定
義するため、このメソッドは単に境界矩形に合わせてクリッピングします。より複雑なオーバーレイ
の場合は、オーバーレイを表すパスに合わせてクリッピングを行う必要があります。この描画コード
の結果を、図 6-4 (78 ページ)に示します。
リスト 6-11 カスタムオーバーレイでのグラデーションの描画
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context
{
// Get the overlay bounding rectangle.
MKMapRect
theMapRect = [self.overlay boundingMapRect];
CGRect theRect = [self rectForMapRect:theMapRect];
// Clip the context to the bounding rectangle.
CGContextAddRect(context, theRect);
CGContextClip(context);
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
76
地図の注釈
地図へのオーバーレイの表示
// Set up the gradient color and location information.
CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[4] = {0.0, 0.33, 0.66, 1.0};
CGFloat components[16] = {0.0, 0.0, 1.0, 0.5,
1.0, 1.0, 1.0, 0.8,
1.0, 1.0, 1.0, 0.8,
0.0, 0.0, 1.0, 0.5};
// Create the gradient.
CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorSpace,
components, locations, 4);
CGPoint start, end;
start = CGPointMake(CGRectGetMidX(theRect), CGRectGetMinY(theRect));
end = CGPointMake(CGRectGetMidX(theRect), CGRectGetMaxY(theRect));
// Draw.
CGContextDrawLinearGradient(context, myGradient, start, end, 0);
// Clean up.
CGColorSpaceRelease(myColorSpace);
CGGradientRelease(myGradient);
}
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
77
地図の注釈
地図へのオーバーレイの表示
図 6-4に、コロラド州を表すオーバーレイ上にカスタムコンテンツを描画した結果を示します。この
場合、オーバーレイレンダラはそのコンテンツをカスタムグラデーションで塗りつぶしています。
図 6-4
カスタムオーバーレイレンダラを使用した描画
デリゲートオブジェクトからのオーバーレイレンダラの作成
オーバーレイレンダラが必要になると、Map Viewはそのデリゲートオブジェクトの
mapView:rendererForOverlay:メソッドを呼び出します。このメソッドを実装していない場合、ま
たは実装していても必ずnilを返す場合、Map Viewは指定されたオーバーレイに対して何も表示しま
せん。そのため、地図に表示したいすべてのオーバーレイについて、このメソッドを実装して有効な
オーバーレイレンダラを返す必要があります。
ほとんどの場合、オーバーレイはそれぞれに異なります。オーバーレイレンダラは必ず
mapView:rendererForOverlay:メソッドで作成する必要がありますが、このオブジェクトをどのよ
うに設定するかに関しては多少の独創性を加える必要があるかもしれません。すべてのレンダラの描
画属性が共通の場合は、このメソッドを、リスト 6-10 (73 ページ)に示した方法と同様の方法で実
装できます。しかし、オーバーレイがそれぞれ異なる色や異なる属性を使用している場合は、
mapView:rendererForOverlay:メソッドに巨大なディシジョンツリーを持たせるのではなく、注釈
オブジェクトを使って情報を初期化する方法を探らなくてはなりません。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
78
地図の注釈
オーバーレイを注釈として使用
オーバーレイは通常は1つ1つ異なるため、地図ビューは、地図から削除されたオブジェクトを再利用
することはありません。既存のオーバーレイレンダラをキューから取り出す代わりに、毎回新しく作
成する必要があります。
複数のオーバーレイオブジェクトの表示
アプリケーションで複数のオーバーレイを扱う場合は、これらのオーバーレイオブジェクトをどのよ
うに管理するかについて検討する必要があります。注釈と同様に、地図に関連付けられているオー
バーレイは、オーバーレイのいずれかの部分が地図上の可視部分と交わるときには常に表示されま
す。また、注釈とは異なり、オーバーレイは地図に比例して拡大縮小するため、オーバーレイ同士が
自動的に重なり合うことはありません。これは、オーバーレイの過密状態を解消するために、オー
バーレイを削除したり後から追加したりする可能性はほとんどないことを意味します。2つのオーバー
レイの境界矩形が重なり合う状況では、オーバーレイの1つを取り除くか、オーバーレイのZ軸におけ
る重なり順を並べ替えて、どのオーバーレイを最前面に表示するかを調整することができます。
MKMapViewクラスのoverlaysプロパティには、登録済みのオーバーレイが、順序付きの配列として
格納されています。この配列内のオブジェクトの順番は、レンダリング時のオブジェクトのZ軸にお
ける重なり順と一致し、配列の先頭のオブジェクトがZ軸における重なり順の一番下を表しています。
あるオーバーレイを残りのすべてのオーバーレイの最前面に配置するには、この配列の最後に追加し
ます。またMap Viewのメソッドを使用して、配列内のさまざまな位置にオブジェクトを挿入したり、
配列内の2つのオブジェクトの位置を入れ替えたりすることができます。
オーバーレイに関して何らかのオーバーラップ検出アルゴリズムを実装する場合は、Map Viewデリ
ゲートのmapView:didAddOverlayRenderers:メソッド内でこれを行います。このメソッドが呼び出
されたときに、MKMapRectIntersectsRect関数を使用して、追加されたオーバーレイがほかのオー
バーレイの境界と交差しているかを確認できます。オーバーラップがある場合は、カスタムロジック
を使用して、どのオーバーレイをレンダリングツリーの最前面に配置すべきかを選び、位置を入れ替
えます(比較ロジックはどのスレッドで発生しても構いませんが、Map Viewはインターフェイス項目
であるため、overlays配列への変更はすべて、アプリケーションのメインスレッド上で同期化し実
行しなければなりません)。
オーバーレイを注釈として使用
MKOverlayプロトコルは、MKAnnotationプロトコルに準拠しています。そのため、オーバーレイオ
ブジェクトはすべて注釈オブジェクトでもあり、コード内ではどちらか一方として扱うことも、両方
として扱うこともできます。オーバーレイオブジェクトをオーバーレイとしても注釈としても扱う場
合、2つの場所でそのオブジェクトを管理するのはデベロッパの責任です。オーバーレイレンダラと
その注釈ビューを両方とも表示したい場合は、アプリケーションデリゲートに
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
79
地図の注釈
オーバーレイを注釈として使用
mapView:rendererForOverlay:メソッドとmapView:viewForAnnotation:メソッドの両方を実装す
る必要があります。また、オブジェクトの追加と削除は、地図のoverlays配列およびannotations
配列の両方で行う必要があります。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
80
道順の提示
Map Kitが提供する、地図ベースの道順提示機能をアプリケーションに組み込むと、次のようなことが
可能になります。
●
●
●
「マップ(Maps)」アプリケーションに、道順を表示するよう指示する
「マップ(Maps)」その他、ユーザのデバイス(iOSのみ)上で動作するアプリケーションを、経路
制御アプリケーションとして登録した上で、ある地点から別の地点への、曲がり角ごとの道順情
報を渡す
汎用の道順情報を取得する
OS X v10.9およびiOS 7.0以降、Map KitにはMKDirectionsという、経路ベースの道順データをAppleの
サーバから取得するAPIが付属しています。アプリケーションはこのMKDirectionsを使って、曲がり
角ごとの道順情報(徒歩に適した形、自動車走行に適した形など)を追加する、目的地までの所要時
間を見積もる、別の経路を示すなど、より質の高い経路情報や道順情報を提供できます。
Map Kitフレームワークの機能を使用するには、Xcodeプロジェクトで「Maps」技術を有効にする必要
があります。
「マップ(Maps)」アプリケーションに道順を表示するよう要求
する
Map Kitは、「マップ(Maps)」アプリケーションを使用して地図の特定の位置情報、または曲がり角ご
とに道順を表示する方法を提供します。これにより、地図データをユーザ自身では表示しない状況に
おける「マップ(Maps)」アプリケーションの使用がサポートされます。たとえば、ユーザアプリケー
ションでは独自の曲がり角ごとの道案内サービスが用意されていない場合に、「マップ(Maps)」アプ
リケーションにこの情報を提示するよう求めることができます。
道順の要求を生成するには、MKMapItemのopenMapsWithItems:launchOptions:メソッドまたは
openInMapsWithLaunchOptions:メソッドを使用します。これらのメソッドは、「マップ(Maps)」ア
プリケーションで表示できるように地図項目を送信します。これらのメソッドに渡す起動オプション
にMKLaunchOptionsDirectionsModeKeyキーが含まれている場合は、「マップ(Maps)」は提供した
始点項目と終点項目との間の道順を表示します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
81
道順の提示
経路制御アプリケーションとして登録する(iOS のみ)
リスト 7-1には、指定された領域を「マップ(Maps)」アプリケーション内で開き、その位置を地図の
中心にするメソッドが示されます。 launchOptionsメソッドのopenMapsWithItems:launchOptions:
パラメータを使用して表示する地図の領域を指定します。
リスト 7-1
「マップ(Maps)」アプリケーションによる位置情報の表示
- (void)displayRegionCenteredOnMapItem:(MKMapItem*)from {
CLLocation* fromLocation = from.placemark.location;
// Create a region centered on the starting point with a 10km span
MKCoordinateRegion region =
MKCoordinateRegionMakeWithDistance(fromLocation.coordinate, 10000, 10000);
// Open the item in Maps, specifying the map region to display.
[MKMapItem openMapsWithItems:[NSArray arrayWithObject:from]
launchOptions:[NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithMKCoordinate:region.center],
MKLaunchOptionsMapCenterKey,
[NSValue valueWithMKCoordinateSpan:region.span],
MKLaunchOptionsMapSpanKey, nil]];
}
「マップ(Maps)」アプリケーションをプログラムから開く方法の詳細については、『MKMapItemClass
Reference 』を参照してください。
経路制御アプリケーションとして登録する(iOS のみ)
ある地点から別の地点への道順を表示できるアプリケーションは、経路制御アプリケーションとして
登録することが可能であり、表示する道順を「マップ(Maps)」アプリケーション、および拡張機能に
よりユーザのデバイスの他のすべてのアプリケーションから利用できるようにできます。経路制御ア
プリケーションとして登録すると、他のアプリケーションからこのアプリケーションに対して経路制
御情報にアクセスする手段が提供されるため、すべてのアプリケーションで独自に道順を提供する必
要がなくなるため、ユーザの利便性が増します。これは開発したアプリケーションを目立たせるため
のよい方法でもあります。「マップ(Maps)」は道順を表示するためのオプションとして、App Storeに
適切な候補として表示されるからです。
道順を提示するアプリケーションとして独自にアプリケーションを登録するには:
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
82
道順の提示
経路制御アプリケーションとして登録する(iOS のみ)
●
●
●
道順の要求を受け付けるようアプリケーションを設定し、着信する経路制御要求を処理するため
のドキュメントタイプを宣言します。
対応地域カバレージファイル(GeoJSONファイルを使用して指定)を使用して、登録するアプリ
ケーションでサポートしている領域を宣言します。
アプリケーションに道順要求URLが送信されてきた場合の処理
道順の要求をアプリケーションで受け入れるための設定
アプリケーションによる道順のサポートを有効にするには、Xcodeでターゲットにするアプリケーショ
ンで次のサポートを設定する必要があります。
●
経路制御要求を有効にし、アプリケーションで提示可能な道順のタイプを指定します。
●
着信する経路制御要求を処理するための特殊なドキュメントタイプを設定します。
iTunes Connectは、すべての経路制御アプリケーションに対して、この2つの項目を求めています。
経路制御要求のサポートは、Xcodeでターゲットの「Capabilities」ペインを開き、「Maps」セクショ
ンの該当する「Routing」チェックボックスで有効にします(設定の手順について詳しくは、『App
Distribution Guide 』の「Configuring an iOS Routing App」を参照)。道順のサポートを追加するには、
MKDirectionsApplicationSupportedModesキーをアプリケーションのInfo.plistファイルに追加
して、選択した交通手段のモードにこのキーの値を設定します。アプリケーションが道順を提示でき
る領域を含んだGeoJSONファイルも提供する必要があります(GeoJSONファイル指定の詳細について
は、“道順でサポートされる対応地域カバレージの宣言” (84 ページ)を参照してください)。
アプリケーションでサポートされる道順のタイプの宣言に加えて、受信する経路制御要求の処理を目
的としたドキュメントタイプをプロジェクトに追加する必要もあります。ドキュメントタイプを追加
するには、ターゲットの「Info」タブにあるXcodeドキュメントタイプエディタを使用します。新しい
ドキュメントタイプを作成し、表 7-1にある情報を使用してタイプに値を設定します。この表に記載
されている値をそのまま正確に使用する必要があります。
表 7-1
道順要求ドキュメントタイプのキーと値
Xcodeの
フィール
ド
値
説明
Name
MKDirectionsRequest
このフィールドの値は任意に設定でき
ますが、推奨された値を使用すること
をお勧めします。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
83
道順の提示
経路制御アプリケーションとして登録する(iOS のみ)
Xcodeの
フィール
ド
値
説明
Types
com.apple.maps.directionsrequest
このキーの値は、道順要求の識別に使
用されるカスタムUTIタイプです。こ
のキーの値は、ここに記載したとおり
でなければなりません。
ドキュメントタイプエディタで行った変更によって、XcodeはアプリケーションのInfo.plistファイ
ルのCFBundleDocumentTypesキーに対応するエントリを追加します。アプリケーションのInfo.plist
ファイルと、このファイルに追加するキーの詳細については、『InformationPropertyListKeyReference 』
を参照してください。
道順でサポートされる対応地域カバレージの宣言
アプリケーションでは道順を提示できる領域に対して地理的領域を宣言する必要があります。対応す
る領域を宣言すると、アプリケーションで処理できない要求についてはシステムから送信されないよ
うになります。たとえば、アプリケーションが提供できる地下鉄の経路情報がニューヨークに限られ
る場合、ロンドンの道順の要求は受信されなくなります。
アプリケーションで対応している領域を宣言するには、GeoJSONファイルを作成してください。この
ファイルはJSON(JavaScript Object Notation)ファイルの一種です。これがアプリケーションの対応地
域カバレージファイルであり、これには1つ以上の地理的領域の境界線を定義する一連の地図の座標
が含まれています。このファイルのフォーマットは、http://geojson.org/geojson-spec.htmlから詳細を
入手できる公開された仕様の一部になっています。
対応地域カバレージファイルは「マップ(Maps)」アプリケーションとApp Storeで使用されますが、ア
プリケーション自身では使用されません。対応地域カバレージファイルをiTunes Connectにアップロー
ドすると、「マップ(Maps)」は対象となる領域で道順を提示できるアプリケーションをApp Storeで検
索できるようになります。対応地域カバレージファイルにより、ユーザがこれらのアプリケーション
の1つをダウンロードすることを希望した場合に情報が提供できるようになります。対応地域カバレー
ジファイルはiTunes Connectにアップロードするので、新しいバージョンのアプリケーションを送信
することなく、いつでもファイルを更新できます。
対応地域カバレージファイルのコンテンツの指定
対応地域カバレージファイルには、対応する地理的領域の境界線を定義する単一のMultiPolygon図
形が含まれている必要があります。単一の複合ポリゴンには複数の子ポリゴンが含まれている場合が
あり、それぞれの子ポリゴンは単一の地理的領域を囲む境界線を定義します。それぞれの子ポリゴン
には、ポリゴンの境界線を定義する4つ以上の座標値が含まれています。GeoJSONの仕様に従って、
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
84
道順の提示
経路制御アプリケーションとして登録する(iOS のみ)
それぞれの子ポリゴンは閉領域、つまり最初の座標値と最後の座標値が必ず同一である必要がありま
す。そのため、最も簡単な図形である三角形の領域を定義する場合でも、4つの点を指定する必要が
あります。もちろん、より複雑なポリゴンを定義したければ、4つ以上の点を使うことになります。
リスト 7-2には、2つの独立した領域(1つはサンフランシスコの周囲、もう1つはシカゴの周囲)を指
定する対応地域カバレージファイルの例が示されています。各領域の座標は、余分と思える括弧に
よって囲われている点に注意してください。それぞれの場合において、最初の左角括弧はポリゴン全
体の開始を表し、2番目の左角括弧は外側の境界線ポリゴンの開始を定義します。そして3番目の左角
括弧は、最初の座標の開始を表します。
リスト 7-2
GeoJSONファイルの例
{ "type": "MultiPolygon",
"coordinates": [
[[[-122.7, 37.3], [-121.9, 37.3], [-121.9, 37.9], [-122.7, 37.9], [-122.7,
37.3]]],
[[[-87.9, 41.5], [-87.3, 41.5], [-87.3, 42.1], [-87.9, 42.1], [-87.9, 41.5]]]
]
}
アプリケーションで領域を定義する際には、次のガイドラインに従うとよいでしょう。
●
●
●
●
領域をできるだけ限定的に定義してください。たとえば、アプリケーションが提供できる地下鉄
の経路情報がニューヨークに限られる場合、ロンドンの道順の要求は受信されなくなります。領
域をより限定的に定義すれば、検索結果に当該アプリケーションが現れる可能性は高くなりま
す。
領域はシンプルな形状を維持し、与えられた地理的領域の周囲を正確な経路をトレースしようと
しないでください。各ポリゴンに含まれる点は20個を超えないようにすることをお勧めします。
領域の定義にこれよりも多くの座標を使用することは可能ですが、非効率的であり通常は不要で
す。システムでは与えられた点がポリゴンの1つの内部にあるかどうかを判別する必要があり、
この判別を行うには、数百の点からなる図形よりも長方形などのシンプルな図形であるほうが容
易です。
MultiPolygon図形の子ポリゴンの数は、20個以下に制限してください。
アプリケーションのカバレージファイルにはMultiPolygon図形のみを使用します。GeoJSONの仕
様では他のタイプの図形もサポートされていますが、経路制御アプリケーションでサポートされ
ているのはMultiPolygon図形のみです。
●
カバレージファイルにはコメントを含めないでください。
●
座標はすべて、経度、緯度の順に指定します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
85
道順の提示
経路制御アプリケーションとして登録する(iOS のみ)
●
カバレージファイルに含まれるポリゴンに、穴があってはなりません。GeoJSONの仕様は穴に対
応していますが、Appleの地図の実装では穴に対応していません。
GeoJSONファイルのiTunes Connectへのアップロード
アプリケーションをiTunes Connectにアップロードする場合、サーバはアプリケーションのInfo.plist
ファイルにMKDirectionsApplicationSupportedModesキーが存在するかどうかをチェックします。
このキーが存在する場合、アプリケーションのiTunes Connectページには、対応地域カバレージファ
イルをアップロードするスペースが含まれています。このファイルはアプリケーションが承認される
前にアップロードする必要があります。詳細については、『iTunes Connect Developer Guide 』の「アプ
リケーションのアイコン、スクリーンショット、およびルーティングアプリケーションファイルの
アップロード」 in iTunes Connect Developer Guide を参照してください。
アプリケーションの対応地域カバレージファイルのデバッグ
GeoJSONファイルをiTunes Connectにアップロードする際には、あらかじめテストするようお勧めしま
す。開発期間中は、Xcodeプロジェクトのスキームオプションを使用してテスト用の対応地域カバレー
ジファイルを指定します。アプリケーションをシミュレータで実行する場合、Xcodeはこのファイル
をシミュレータまたはデバイスに転送するため、「マップ(Maps)」アプリケーションはアプリケー
ションが認識している領域について認識しています。
テスト用の対応地域カバレージファイルを指定するには:
1.
プロジェクトのスキームエディタを開きます。
2.
プロジェクトの「Run (Debug)」スキームを選択します。
3.
「Options」タブの「Routing App Coverage File」ポップアップメニューでカバレージファイルを選
択します。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
86
道順の提示
経路制御アプリケーションとして登録する(iOS のみ)
するとスキームエディタが現れます(図 7-1を参照)。
図 7-1
スキームエディタでGeoJSONファイルを選択している様子
デバイスまたはシミュレータ上にアプリケーションをインストール後、アプリケーションを終了し、
「マップ(Maps)」アプリケーションを起動して道順の始点と終点を指定します。対応地域カバレージ
ファイルが有効で、指定した2つの地点を含んでいる場合、テストするアプリケーションが表示され
るはずです。アプリケーションが表示されない場合は、地理的領域の地点が正しいことを確認しま
す。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
87
道順の提示
URLによる道順要求の取り扱い
注意: シミュレータ内で実行している場合に、「マップ(Maps)」で使用できるオプションの
1つとしてアプリケーションが表示されない場合は、「Console」アプリケーションにエラー
メッセージが表示されていないかを確認します。「マップ(Maps)」は、アプリケーションの
GeoJSONを読み込むときに発生したすべての問題をXcodeではなくコンソールに出力して報
告します。
URLによる道順要求の取り扱い
システムはURLを使用して道順要求を経路制御その他のアプリケーションに送信します。たとえば、
ユーザが「マップ(Maps)」アプリケーションに道順を問い合わせ、このアプリケーションが選択され
ると、「マップ(Maps)」は始点と終点を含んだURLを作成して、これを開くようにアプリケーション
に要求してきます。アプリケーションでは他のURLを開くときと同様に、アプリケーションの
application:openURL:sourceApplication:annotation:メソッドを使用してこのURLを開く処理
を行います。ただし、URLを処理する手順は他のURLの場合よりも多少複雑になっています。
アプリケーションで開くURLを受信するると、アプリケーションの
application:openURL:sourceApplication:annotation:メソッドでは次の手順を実行する必要が
あります。
1.
URLに道順要求が埋め込まれているかどうか確認するため、MKDirectionsRequestの
isDirectionsRequestURL:クラスメソッドを呼び出します。URLに道順要求が埋め込まれている
場合は、次の手順に進みます。
2.
提示されたURLを使用してMKDirectionsRequestオブジェクトを作成します。
3.
MKDirectionsRequestオブジェクトから経路の始点と終点を取得します。
始点と終点はMKMapItemオブジェクトとして指定されます。このオブジェクトには位置の地理的
な座標のほかに、追加情報が含まれていることがあります。MKMapItemオブジェクトがユーザの
現在位置を表している場合は、Core Locationで自分自身の実際の座標位置を取得してください。
4.
カスタムロジックを使用して、経路の計算と表示を行います。
前の手順はすべてのアプリケーションで同一であるため、リスト 7-3に示されているものと同様のコー
ドをapplication:openURL:sourceApplication:annotation:メソッドに含めることができます。
最も大事な追加点は、経路情報を計算してアプリケーションに表示することです。アプリケーション
で他のURLのタイプも扱う場合は、それらのURLを処理するコードも個別に含める必要があります。
リスト 7-3
道順要求URLの処理
- (BOOL)application:(UIApplication *)application
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
88
道順の提示
汎用の道順情報の取得
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if ([MKDirectionsRequest isDirectionsRequestURL:url]) {
MKDirectionsRequest* directionsInfo = [[MKDirectionsRequest alloc]
initWithContentsOfURL:url];
// TO DO: Plot and display the route using the
//
source and destination properties of directionsInfo.
return YES;
}
else {
// Handle other URL types...
}
return NO;
}
MKDirectionsに渡す要求を生成するためにMKDirectionsRequestクラスも使います。このAPIの使
い方について詳しくは、“汎用の道順情報の取得”を参照してください。
汎用の道順情報の取得
アプリケーションはMKDirectionsのAPIを使って、経路に関する情報(距離、見積もり所要時間、
ローカライズ済みの注記、当該経路を構成する個々の行程など)を取得できます。たとえば鉄道経路
を表示するアプリケーションの場合、出発地から発駅、着駅から目的地までの徒歩経路に関する情報
を要求する、といったことが考えられます。
注意: MKDirectionsで生成する道順要求はサーバベースなので、ネットワーク接続を要し
ます。
要求の量に、アプリケーションごと、あるいは開発者IDごとの制限はないので、適切に動作
するアプリケーションであれば、問題が生じることはないでしょう。しかし、野放図に大量
の要求を生成すれば、通信路に障害が発生する恐れがあります。
汎用の道順情報を取得するには:
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
89
道順の提示
汎用の道順情報の取得
1.
MKDirectionsRequestオブジェクトを生成し、経路の起点と終点を表すMKMapItemオブジェクト
を渡して初期化します。交通手段(徒歩、自動車など)を指定する場合は、要求オブジェクトの
transportTypeプロパティを使います。
2.
MKDirectionsオブジェクトを生成し、手順1で生成した要求オブジェクトを渡して初期化しま
す。
3.
経路検索処理を開始します。結果を処理するブロックを渡して、
calculateDirectionsWithCompletionHandler:を実行してください。
4.
完了ハンドラに渡されたMKDirectionsResponseオブジェクトの経路情報を参照し、必要な処理
を行います(応答オブジェクトにはMKRouteオブジェクトの配列が収容されています。この配列
の各要素で、起点から終点に到る、何通りかの経路を表すようになっています)。
リスト 7-4に、道順要求を生成し、経路(1通り)を求め、その結果を処理するコード例を示します。
リスト 7-4
道順の要求
MKDirectionsRequest *walkingRouteRequest = [[MKDirectionsRequest alloc] init];
walkingRouteRequest.transportType = MKDirectionsTransportTypeWalking;
[walkingRouteRequest setSource:[startPoint mapItem]];
[walkingRouteRequest setDestination :[endPoint mapItem]];
MKDirections *walkingRouteDirections = [[MKDirections alloc]
initWithRequest:walkingRouteRequest];
[walkingRouteDirections
calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *
walkingRouteResponse, NSError *walkingRouteError) {
if (walkingRouteError) {
[self handleDirectionsError:walkingRouteError];
} else {
// The code doesn't request alternate routes, so add the single calculated
route to
// a previously declared MKRoute property called walkingRoute.
self.walkingRoute = walkingRouteResponse.routes[0];
}
}];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
90
道順の提示
汎用の道順情報の取得
経路オブジェクトは、ある1通りの経路のジオメトリを表し、地図上にオーバーレイ表示するための
折れ線オブジェクトも保持しています。代替経路を要求した場合、完了ハンドラに渡される応答オブ
ジェクトには、routes配列の形で複数の経路オブジェクトが収容されています。リスト 7-5に、経路
配列の要素である代替要素それぞれについて、経路を表す折れ線を表示するコード例を示します。
リスト 7-5
代替経路の表示
- (void) myShowDirections:(MKDirectionsResponse *)response {
self.response = response;
for (MKRoute *route in self.response.routes) {
[self.mapView addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
}
}
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
91
検索機能の組み込み
ユーザが入力した問い合わせ文字列にもとづく検索機能を組み込めるよう、Map KitにはMKLocalSearch
というAPIがあります。アプリケーションはこのAPIを使って、名称、住所、建物の種類(喫茶店、劇
場など)の記述にもとづく、場所の検索機能を組み込むことができます。
ローカル検索とジオコーディングはよく似た機能ですが、用途は異なります。ジオコーディングは、
地図上の座標を、Address Bookで使われているような構造化した住所に(あるいはその逆に)変換す
るために使います。これに対してローカル検索は、ユーザが入力した字句に合致する場所を検索する
のが目的です。
注意: MKLocalSearchによる検索要求はサーバベースなので、ネットワーク接続を要しま
す。
要求の量に、アプリケーションごと、あるいは開発者IDごとの制限はないので、適切に動作
するアプリケーションであれば、問題が生じることはないでしょう。しかし、野放図に大量
の要求を生成すれば、通信路に障害が発生する恐れがあります。
ユーザが検索欄に入力した字句に合致する場所を検索するには:
1.
MKLocalSearchRequestオブジェクトを生成し、ユーザが自然言語で入力した問い合わせ文字列
を指定します。
(必要ならば)地域を定義して、検索結果を絞り込みます。適切な結果が得られるよう、できる
だけ地域を定義するとよいでしょう。
2.
MKLocalSearchオブジェクトを生成し、手順1で生成した検索要求を渡して初期化します。
3.
検索を開始します。結果を処理する完了ハンドラブロックを渡して、
startWithCompletionHandler:を実行してください。
それぞれのMKLocalSearchオブジェクトは、1件の検索のみをおこないます。複数件の検索をおこな
うためには、それぞれについて検索要求を定義し、検索オブジェクトを生成しなければなりません。
検索は非同期に実行されるので、それぞれを並列に実行し、結果が届くのを待って処理することにな
ります。
ローカル検索の結果は、MKMapItemオブジェクトの集合として返されます。地図項目オブジェクトに
は次のような属性があります。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
92
検索機能の組み込み
●
該当箇所の地図座標
●
該当箇所を表す構造化された住所
●
名称、電話番号、URL(会社などの場合)
リスト 8-1に、検索要求を生成し、ローカル検索の初期化を行い、検索結果を注釈として地図上に表
示するコード例を示します。
リスト 8-1
ユーザ入力に合致する場所を検索するコード例
// Create and initialize a search request object.
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = query;
request.region = self.map.region;
// Create and initialize a search object.
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
// Start the search and display the results as annotations on the map.
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError
*error)
{
NSMutableArray *placemarks = [NSMutableArray array];
for (MKMapItem *item in response.mapItems) {
[placemarks addObject:item.placemark];
}
[self.map removeAnnotations:[self.map annotations]];
[self.map showAnnotations:placemarks animated:NO];
}];
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
93
書類の改訂履歴
この表は「位置情報とマッププログラミングガイド 」の改訂履歴です。
日付
メモ
2014-03-10
iOS 7およびOS X v10.9で導入された、Map Kitの機能を解説しました。
付録「従来のマップ技術」を削除しました。
2013-10-24
ビーコンとして使えるデバイスの型を修正しました。
2013-09-18
新しいCore LocationのiBeaconについての情報を追加しました。
この文書は以前は『Location and Maps Programming Guide 』という
タイトルでした。
バックグラウンドでの位置情報サービスの使用に関する情報を追加
しました。詳しくは“バックグラウンドでの位置情報イベントの取
得(iOSのみ)” (17 ページ) を参照してください。
2012-09-19
独自の道順情報をサポートする方法について、情報を追加しまし
た。
2011-10-12
新しいCore LocationのGeocoderについての情報を追加しました。
2010-05-20
領域観測についての情報を追加しました。
オーバーレイの作成についての情報を追加しました。
地図と注釈についての既存の情報に補足を加えました。
ユーザの位置を取得する新しいテクノロジーを盛り込むように、位
置情報関連のセクションを更新しました。
2014-03-10 | Copyright © 2014 Apple Inc. All Rights Reserved.
94
Apple Inc.
Copyright © 2014 Apple Inc.
All rights reserved.
本書の一部あるいは全部を Apple Inc. から書
面による事前の許諾を得ることなく複写複製
(コピー)することを禁じます。また、製品
に付属のソフトウェアは同梱のソフトウェア
使用許諾契約書に記載の条件のもとでお使い
ください。書類を個人で使用する場合に限り
1 台のコンピュータに保管すること、またそ
の書類にアップルの著作権表示が含まれる限
り、個人的な利用を目的に書類を複製するこ
とを認めます。
Apple ロゴは、米国その他の国で登録された
Apple Inc. の商標です。
キーボードから入力可能な Apple ロゴについ
ても、これを Apple Inc. からの書面による事
前の許諾なしに商業的な目的で使用すると、
連邦および州の商標法および不正競争防止法
違反となる場合があります。
本書に記載されているテクノロジーに関して
は、明示または黙示を問わず、使用を許諾し
ません。 本書に記載されているテクノロジー
に関するすべての知的財産権は、Apple Inc.
が保有しています。 本書は、Apple ブランド
のコンピュータ用のアプリケーション開発に
使用を限定します。
本書には正確な情報を記載するように努めま
した。 ただし、誤植や制作上の誤記がないこ
とを保証するものではありません。
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
U.S.A.
Apple Japan
〒106-6140 東京都港区六本木 6
丁目10番1号 六本木ヒルズ
http://www.apple.com/jp
Offline copy. Trademarks go here.
Apple Inc. は本書の内容を確認しておりますが、本
書に関して、明示的であるか黙示的であるかを問わ
ず、その品質、正確さ、市場性、または特定の目的
に対する適合性に関して何らかの保証または表明を
行うものではありません。その結果、本書は「現状
有姿のまま」提供され、本書の品質または正確さに
関連して発生するすべての損害は、購入者であるお
客様が負うものとします。
いかなる場合も、Apple Inc. は、本書の内容に含ま
れる瑕疵または不正確さによって生じる直接的、間
接的、特殊的、偶発的、または結果的損害に対する
賠償請求には一切応じません。そのような損害の可
能性があらかじめ指摘されている場合においても同
様です。
上記の損害に対する保証および救済は、口頭や書面
によるか、または明示的や黙示的であるかを問わ
ず、唯一のものであり、その他一切の保証にかわる
ものです。 Apple Inc. の販売店、代理店、または従
業員には、この保証に関する規定に何らかの変更、
拡張、または追加を加える権限は与えられていませ
ん。
一部の国や地域では、黙示あるいは偶発的または結
果的損害に対する賠償の免責または制限が認められ
ていないため、上記の制限や免責がお客様に適用さ
れない場合があります。 この保証はお客様に特定
の法的権利を与え、地域によってはその他の権利が
お客様に与えられる場合もあります。
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertising