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

アプリ内でWebページを開いてiOS標準アプリと連携するにはiOSでジオ(GEO)プログミラング入門(3)(3/3 ページ)

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

モーダルへ処理を委譲するプロトコルを作る

 UIViewControllerおよび、そのサブクラスを「モーダル」(モーダルダイアログ)として表示するには、UIViewControllerクラスの「presentModalViewController」メソッドを利用します。そのために、CustomAnnotationViewのボタンタップ時の処理をGeoPhotoViewControllerに委譲する仕組みを作ります。

 GeoPhotoViewControllerとCustomAnnotationViewの仲立ちをするためのデリゲートを定義します。プロトコルの命名は、「{イベント送信元の名前}+Delegate」というのが通例です。通例に従って、CustomAnnotationViewDelegateで発生したイベントを受ける側のプロトコルの名前はCustomAnnotationViewDelegateとします。

 Xcodeのメニューバーから[File]→[New]→[New File...]を選び、プロトコルのひな型である[Objective-C protocol]を選択し、「CustomAnnotationViewDelegate.h」を作成します。

図10 [Objective-C protocol]を選択 図10 [Objective-C protocol]を選択
図11 「CustomAnnotationViewDelegate.h」を作成 図11 「CustomAnnotationViewDelegate.h」を作成

 このプロトコルには、「openUrl」というメソッドを定義します。

#import <Foundation/Foundation.h>
#import “Photo.h”
 
@protocol CustomAnnotationViewDelegate <NSObject>
 
- (void) openUrl : (Photo *) photo;
 
@end
CustomAnnotationViewDelegate.h

 ヘッダファイルを編集し、GeoPhotoViewControllerがCustomAnnotationViewDelegateに準拠するようにします。

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import "FlickrPhotoParser.h"
#import "CustomAnnotationViewDelegate.h"
#import "Photo.h"
#import "WebViewController.h"
 
@interface GeoPhotoViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, CustomAnnotationViewDelegate> {
GeoPhotoViewController.h(青い部分が変更個所)

 CustomAnnotationViewDelegateに定義したopenUrlメソッドを実装します。

- (void) openUrl : (Photo *) photo {
    [self presentModalViewController:webViewController animated:YES];
    [webViewController openUrl: photo];
}
GeoPhotoViewController.m

 ここで、GeoPhotoViewControllerのモーダルダイアログとしてWebViewControllerを表示しています。引数の「animated」の値が「真」ならば表示するときに下からピョコンと飛び出すアニメーションが入ります。「偽」ならば、いきなり表示します。

CustomAnnotationViewを改造して実行

 「受け手」側であるWebViewControllerの実装が完了したので、最後に「送り手」側のCustomAnnotationViewを改造します。

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "Photo.h"
#import "CustomAnnotationViewDelegate.h"
 
@interface CustomAnnotationView : MKAnnotationView {
    id<CustomAnnotationViewDelegate> delegate;
}
 
@property (nonatomic, retain) id<CustomAnnotationViewDelegate> delegate;
 
-(void) showDetail: (id) sender;
    
@end
CustomAnnotationView.h
#import "CustomAnnotationView.h"
 
@implementation CustomAnnotationView
 
@synthesize delegate;
 
- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
                delegate:(id<CustomAnnotationViewDelegate>) _delegate {
    
    [self setDelegate:_delegate];
    
    [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
    self.image = [UIImage imageNamed:@"flag.png"];
    
    self.canShowCallout = YES;
    
    UIButton* button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [button addTarget:self action:@selector(showDetail:) 
     forControlEvents:UIControlEventTouchUpInside];
    self.rightCalloutAccessoryView = button;
    
    return self;
}
 
-(void) showDetail: (id) sender {
    [self.delegate openUrl: (Photo*)self.annotation];
}
 
@end
CustomAnnotationView.m

 ここで、いったん実行してみます。

図12 実行結果 図12 実行結果

iOSは、URLで他のアプリを開ける

 今回のラストは、先ほどスタブのままになっていた「iOSの標準の地図アプリを開く」という部分、WebViewControllerクラスのopenInExternalViewメソッドの実装です。

 iOSには、「特定のパターンのURLを開こうとすると特定のアプリで開く」という機能があります。例えば、以下のようなURLスキームに反応します。

  • 「tel:」で始まるURLで、電話をかける
  • 「mailto:」で始まるURLで、メーラーを開く
  • 「sms:」で始まるURLで、SMSを作成する

 また、特殊なURLスキーム以外にも以下があります。

  • 「http://www.youtube.com」で始まるURLを開こうとすると、YouTubeアプリで再生
  • 「http://maps.google.com/maps」で始まるURLを開こうとすると、地図アプリが開く

 本記事では詳しくは述べませんが、アプリ開発者は、独自のURLスキームに反応して立ち上がるアプリを作ることもできます。詳細は、以下の記事を参照してください。


 このような機能を使うことで、アプリ同士が連携できます。Webページ上のリンクをタップした場合でも、アプリから「UIApplication」クラスの「openURL」メソッドを使ってURLを開く場合でも、同じように機能します。

 今回は、「http://maps.google.com/maps」で始まるURLを地図アプリで開くという機能を使います。中心の緯度経度を指定して地図を開くなら、「http://maps.google.com/maps?ll={緯度},{経度}」という具合にパラメータを付けます。詳しくは、「iOS Developer Library」の「Map Links」をご覧ください。

 Photoオブジェクトの緯度経度情報を使ってURLを生成し、UIApplication.openURLで開きます。

- (IBAction) openInExternalMap: (id) sender {
    NSString *urlString = [NSString stringWithFormat: @"http://maps.google.com/maps?ll=%f,%f",
        photo.coordinate.latitude, photo.coordinate.longitude];
    NSLog(@"WebViewController.openInExternalMap URL=%@", urlString);
    [[UIApplication sharedApplication] openURL:[[NSURL alloc] initWithString: urlString]];
}
WebViewController.m

 これを実行すると、Safariではなく、iOSの標準の地図アプリ(Map.app)が開きます。

次回は、サムネイルを並べる

 今回は、ここまでです。次回は、ネットワーク経由で取得した画像をアノテーションとして地図に配置し、地図にサムネイルを表示するようにし、地図の表示範囲を変更したら、新たなデータを読み込むという改良を行います。

図13 次回はサムネイルを並べる 図13 次回はサムネイルを並べる

著者紹介

株式会社鳥人間

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

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


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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