このエントリーをはてなブックマークに追加このエントリをつぶやく

地図アプリの作成-iPhone版その2

だいぶ間が空いてしまいました。
iPhone版の第2回です。
今回はいよいよ位置情報サービスを扱います。

自分の位置を表示する

iPhone版では、何らかの位置を表示するにはMKAnnotationを使用します。また位置以外の範囲(円など)を表示するにはOverlayを使用します。
というのがまあ概論なのですが、MKMapViewには非常に簡単な手段が用意されています。
[cce_objc]
mapView.showsUserLocation = YES;
[/cce_objc]
この1行を追加するだけで位置情報サービスが有効になり(ステータスバーに三角形のマークがでます)、自位置に丸いマーカーが表示されます。
ただし、地図の位置は変わりませんので自分で追尾させる必要があります。

MKAnnotation/Overlayについては次回に説明する予定です。

iOSにおける位置情報サービス

iOSにおける位置情報サービスは主に2つあります
1つはStandard Location Updatesと呼ばれる、一般的なGPSの動作モード
もう1つはiOS4から導入されたSignificant Location Updatesと呼ばれる、ネットワーク位置情報を基にした動作モード
です。

Standard Location Updatesは主にGPSをつかって測位するようです。ただしGPSの載っていないiPodやiPadなどではWiFiベースの測位を用いるようです。(Androidと違いiOSではどの位置情報ソースを用いて測位されたかを判断する手段は無いので確実なことは言えませんが…)
Significant Location Updatesはそれほど頻度の高い位置情報の更新を必要としない場合に用います。
ネットワーク位置情報(3G/WiFi)をベースにするので電池の消耗が少なく、大きく位置を移動したとき(3Gでは基地局が変わったときと言われています)のみ通知されるのが特徴です。

さて、地図アプリを作るとなれば、自分の位置を常に表示してほしいもの。
ですので、Standard Location Updatesを使って位置情報を取得し、mapViewに反映することにしましょう。

位置情報サービスを使う

CLLocationManagerDelegateを実装します。
[cce_objc]
@interface MapViewController : UIViewController <CLLocationManagerDelegate> {
MKMapView *mapView;
CLLocationManager *locationManager;
}

@end
[/cce_objc]
[cce_objc]
#pragma mark CLLocationManagerDelegate
– (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[mapView setCenterCoordinate:newLocation.coordinate animated:YES];
}
[/cce_objc]
CLLocationManagerDelegateにはいくつかのセレクタが定義されていますが、必要なのは1つです。
 - locationManager:didUpdateToLocation:fromLocation:
このセレクタは位置情報が更新されたときに呼び出されます。
CLLocationには以下のプロパティがあります
・coordinate
 緯度経度を表すCLLocationCoordinate2Dクラス
 coordinate.latitude – 緯度。マイナス値は南緯、プラスが北緯
 coordinate.longitude – 軽度。マイナス値は西経、プラスが東経
 単位は度
・altitude
 海面からの高度を表す。単位はメートル
・horizontalAccuracy
 水平方向の精度。単位はメートル
・verticalAccuracy
 垂直方向の精度。単位はメートル
・timestamp
 側位した時刻
・speed
 速度。単位はメートル毎秒
・course
 方位。北を0度として時計回りに360度までの値を取る

mapViewのsetCenterCoordinateはCLLocationCoordinate2Dを引数としてとるので、newLocation.coordinateをそのまま渡しています。

残りを記述していきましょう。
LocationServiceが使えるなら、CLLocationManagerを取得しdelegateを設定します
[cce_objc]
– (id)init {
self = [super init];
if (self) {
// Custom initialization.
if ([CLLocationManager locationServicesEnabled]) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
}
return self;
}
[/cce_objc]

ここではCLLocationManagerのプロパティ2つに値を設定しています。
ひとつはdistanceFilterで、位置情報の更新を一定の距離間隔で行いたい場合に指定します。
デフォルトはkCLDistanceFilterNoneで、この場合は距離での更新をおこないません。
ナビのように一定間隔で地図上に点を打っていくようなアプリにはもってこいでしょうか。

もうひとつはdesiredAccuracyで、アプリにとって望ましい位置情報の正確さを設定します。指定できる値としては
精度の高い方から
・kCLLocationAccuracyBestForNavigation
 ナビアプリ等最高精度を必要とするアプリが指定
 GPSだけでなくセンサーの値等も利用して位置情報を生成するようです。iOS4以降で指定可能。
・kCLLocationAccuracyBest
 iOS3までの最高精度
・kCLLocationAccuracyNearestTenMeters
 だいたい10mくらいの精度
・kCLLocationAccuracyHundredMeters
 だいたい100mくらいの精度
・kCLLocationAccuracyKilometer
 約1kmくらいの精度
・kCLLocationAccuracyThreeKilometers
 約3kmくらいの精度
があります。
どれを指定すればどの位置情報サービスを使うか、等は明記されていません。だいたいの予測はつきますけどね…

そして、viewの表示開始で位置情報の取得を開始
[cce_objc]
– (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[locationManager startUpdatingLocation];
}
[/cce_objc]

viewの表示終了で位置情報の取得を終了します。
[cce_objc]
– (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[locationManager stopUpdatingLocation];
}
[/cce_objc]

これで実行すれば、自分の位置を追跡する地図の完成です。

藤田 の紹介

スピリテックのCTOで今ココなう!の中の人。
カテゴリー: プログラミング   タグ: , ,   この投稿のパーマリンク

コメントは受け付けていません。