連載
» 2011年04月04日 00時00分 公開

iOSでジオ(GEO)プログミラング入門(1):iPhoneアプリで位置情報と地図を使うための基礎知識 (3/3)

[郷田まり子,株式会社鳥人間]
前のページへ 1|2|3       

アノテーションを追加するには

 次は、アノテーションを追加してみます。

 表示すべきデータのモデル(Model)と、それを実際に表示するときの見た目(View)は分離されます。モデルを表すのが「MKAnnotation」プロトコル、見た目を実装するのが「MKAnnotationView」クラスです。

 簡単なアノテーションの作成のために、「CustomAnnotation」クラスを追加します。座標とタイトル・サブタイトルを持ったシンプルなクラスで、「MKAnnotation」に定義されているプロパティを備えます。

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface CustomAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *annotationTitle;
NSString *annotationSubtitle;
}

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, retain) NSString *annotationTitle;
@property (nonatomic, retain) NSString *annotationSubtitle;
- (id)initWithLocationCoordinate:(CLLocationCoordinate2D) _coordinate
title:(NSString *)_annotationTitle subtitle:(NSString *)_annotationannSubtitle;
- (NSString *)title;
- (NSString *)subtitle;

@end
CustomAnnotation.h
#import "CustomAnnotation.h"
 
@implementation CustomAnnotation
@synthesize coordinate;
@synthesize annotationTitle;
@synthesize annotationSubtitle;
 
- (NSString *)title {  
    return annotationTitle;
}
 
- (NSString *)subtitle {  
    return annotationSubtitle;
}
 
- (id)initWithLocationCoordinate:(CLLocationCoordinate2D) _coordinate
    title:(NSString *)_annotationTitle subtitle:(NSString *)_annotationSubtitle {
    coordinate = _coordinate;
    self.annotationTitle = _annotationTitle;
    self.annotationSubtitle = _annotationSubtitle;
    return self;
}
 
- (void) dealloc {
    [annotationTitle release];
    [annotationSubtitle release];
    [super dealloc];
}
 
@end
CustomAnnotation.m

 「MKMapView#adAnnotation」メソッドを使ってアノテーションを追加します。

    [mapView addAnnotation:
        [[[CustomAnnotation alloc]initWithLocationCoordinate:CLLocationCoordinate2DMake(35.685623,139.763153)
            title:@"大手町駅"
            subtitle:@"千代田線・半蔵門線・丸ノ内線・東西線・三田線"]autorelease]];
    [mapView addAnnotation:
        [[[CustomAnnotation alloc]initWithLocationCoordinate:CLLocationCoordinate2DMake(35.690747,139.756866)
            title:@"竹橋駅"
            subtitle:@"東西線"]autorelease]];
    [mapView addAnnotation:
        [[[CustomAnnotation alloc]initWithLocationCoordinate:CLLocationCoordinate2DMake(35.681666,139.764869)
            title:@"東京駅"
            subtitle:@"いっぱい"]autorelease]];
GeoPhotoViewController#viewDidLoad

 動かしてみたところ、ピンをタップすると、タイトルとサブタイトルが表示されるます。

デフォルトの赤いピンをカスタマイズするには

 アノテーションをカスタマイズすることもできます。オリジナルのアノテーションを作るためには、「MKAnnotationView」クラスを拡張します。

 今回は、デフォルトの赤いピンの代わりに、リソースファイルとして追加した画像「flag.png」を表示するという簡単なカスタマイズを行います。

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface CustomAnnotationView : MKAnnotationView {
}

@end
CustomAnnotationView.h
#import "CustomAnnotationView.h"
@implementation CustomAnnotationView

- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
[super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
self.image = [UIImage imageNamed:@"flag.png"];
return self;
}

@end
CustomAnnotationView.m

 「MKMapView」にデリゲート(「MKMapViewDelegate」プロトコルを実装)をセットすると、アノテーションを表示する必要が生じたタイミングで、そのデリゲートの「viewForAnnotation」メソッドが呼ばれます。そこで、「MKAnnotationView」を返せば、地図上に表示されます。「nil」を返せば、デフォルトのビュー(赤いピンと黒い半透明の吹き出し)が表示されます。

 MKAnnotationView(および、そのサブクラス)は、種類ごとに再利用し、「使い回し」する仕組みがあります。「MKMapView#dequeueReusableAnnotationViewWithIdentifier」メソッドを使うと、「その種類のアノテーションビューで、使い回しできるもの」が返されます。

 再利用可能なアノテーションビューがあれば、そのビューを取得し、必要ならばアノテーションの内容に合わせてデータの流し込みなどを行います。再利用可能なアノテーションビューがなければ「nil」が返されるので、そのときだけ、新しいMKAnnotationViewインスタンスを生成する、という使い方をします。

 「UITableView」「UITableViewCell」を使ったことのある方なら、「セルの再利用」で似たような実装をしたことがあるでしょう。

 「GeoPhotoViewController.h」宣言部分に下記の太字部分を追加します。

@interface GeoPhotoViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate> {

 GeoPhotoViewController#viewDidLoadに追加します。

    [mapView setDelegate: self];

 GeoPhotoViewController.mに「viewForAnnotation」メソッドを追加します。

-(MKAnnotationView*)mapView:(MKMapView*)mapView 
viewForAnnotation:(id <MKAnnotation>)annotation {

if (annotation == mapView.userLocation) { //……【2】
return nil;
} else {
CustomAnnotationView *annotationView;
NSString* identifier = @"flag"; // 再利用時の識別子

// 再利用可能な MKAnnotationView を取得
annotationView = (CustomAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];

if(nil == annotationView) {
//再利用可能な MKAnnotationView がなければ新規作成
annotationView = [[[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier] autorelease];
}
annotationView.annotation = annotation;
return annotationView;
}
}

 実は、「ユーザーの現在地」も、アノテーションの一種として扱われます。そして、「ユーザーの現在地」を表すアノテーションに対しては、デフォルトでは青いドットが表示されます。

 ちなみに、ユーザーの現在地を表示する/しないの切り替えは、MKMapViewの「showsUserLocation」プロパティで行います。

 【2】の部分をご覧ください。渡された「MKAnnotation」が「ユーザーの現在地」であれば「nil」を返すという処理を行っています。こうすると、現在地には、青いドットを、それ以外の場所にはカスタマイズした旗のアイコンを表示します。

今後は、Flickr APIとマッシュアップ

 本稿では、「現在地の近辺で撮影された写真を地図上に表示するアプリ」を作るために、基礎としてCoreLocationとMapKitの2つのフレームワークの使い方を中心に解説しました。

 最後の章では、アプリのリソースとして画像を用意しましたが、ここに、ネットワーク経由で取得した画像などを使うことももちろんできます。今後以下の予定で連載をする予定ですが、第3回ではFlickr APIを使って取得した写真のサムネイルを地図にする方法を解説しますので、お楽しみに。

  • 第1回:測位機能と地図の基礎を学ぶ(終了)
  • 第2回:XMLパーサの作り方を学ぶ。マッシュアップの準備として、Flickr APIのパーサを書く
  • 第3回:Flickr APIを使って取得した情報を使って、地図上に近所の写真のサムネイルを表示。さらに、アプリケーションのブラッシュアップを行う

著者紹介

株式会社鳥人間

郷田まり子(ごうだまりこ)

1980年東京生まれ、プログラマ。建築製図から人工衛星観測まで、ユーザーに驚きをもたらす数々のWebサービスを実装してきたs。現在、創業二年社員二名の株式会社鳥人間にて、主にWeb開発案件を手掛ける。本業の傍ら、目新しくて面白そうな物にはとりあえず飛びついてハックしている



前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。