藤田です
3/11はひどい地震でしたね…
幸いなことに弊社(東京都新宿区)は揺れただけで、物が破損したりということは特にありませんでした。ただ電車の復旧が遅くなったので帰れなかった人が多かったみたいです。
さて、スピリテックでは社員持ち回りで技術ブログを書いていく事になりました。既に谷、井上のエントリが上がっておりますが、基本的に一人当たり1ヶ月に1本は投稿しよう、ということになっています。
で、私の担当のお題はというと「地図アプリの作り方」です。今ココなう!を提供しているので、今ココなう!クライアントアプリの一端をここで公開していきたいと思います。現状、地図アプリといえるのはiPhone用くらいですが、Android版も解説していきますよ!
今回はiPhoneアプリで地図を出すところまでを解説します。ある程度XCode並びにObjective-Cに慣れている人を対象としますので、わからないことがあったらググりましょう。
プロジェクトの作成と初期準備
最初に空のプロジェクトを作成します。
私はInterface Builderを使わない派なので、IB関係のファイルは削除してしまいます。
MainWindow.xibを削除
Other Sources/main.mを修正
UIApplicationMainの第4引数にAppDelegateクラス名を渡します。
[cce_objc]int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @”MapAppDelegate”);
[pool release];
return retVal;
}
[/cce_objc]
MapApp-Info.plistを修正
- Main nib file base nameを空に
- Status bar is initially hiddenを追加してチェックを入れる
- Bundle identifierを自分の環境に合わせましょう
ここまでで、ViewのないWindowだけのアプリケーションがコンパイルできます。
ViewController追加の準備
まずCoreLocation.framework、MapKit.frameworkをプロジェクトに追加しましょう。
次に新規ファイルを追加でCocoa Touch ClassのUIViewController subclassを選択します
3つあるチェックボックスは全部外しておきます。
ファイルの名前はMapViewControllerとしておきましょう
っと、地図Viewの中身をつくる前に、このViewControllerをMainViewとして使うためのコードを追加します
MapAppDelegate.h
[cce_objc]#import
#import “MapViewController.h”
@interface MapAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MapViewController *mapViewController;
}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) MapViewController *mapViewController;
@end[/cce_objc]
MapAppDelegate.m
[cce_objc]@synthesize mapViewController;
– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ステータスバーの表示
[UIApplication sharedApplication].statusBarHidden = NO;
// メインウィンドウの作成
window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 地図ViewControllerの作成
mapViewController = [[MapViewController alloc] init];
[self.window addSubview:mapViewController.view];
// ウィンドウの表示
[self.window makeKeyAndVisible];
return YES;
}
– (void)dealloc {
[window release];
[mapViewController release];
[super dealloc];
}[/cce_objc]
ここまでで、Viewを表示する準備ができました。
ViewControllerの作成
それでは地図用のViewControllerを作っていきましょう。
MapViewController.h
[cce_objc]#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface MapViewController : UIViewController {
MKMapView *mapView;
}
@end[/cce_objc]
MapViewController.m
[cce_objc]#import “MapViewController.h”
@implementation MapViewController
// 初期化
– (id)init {
self = [super init];
if (self) {
// Custom initialization.
}
return self;
}[/cce_objc]
初期化コードです。現在は特に特別なことはしていません。
[cce_objc]// Implement loadView to create a view hierarchy programmatically, without using a nib.
– (void)loadView {
UIView *v = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
mapView = [[MKMapView alloc] initWithFrame:v.frame];
mapView.zoomEnabled = YES;
mapView.scrollEnabled = YES;
[v addSubview:mapView];
self.view = v;
[v release];
}[/cce_objc]
Interface Builderを使わない場合、-[UIView loadView]でViewを作成する必要があります。
最初のUIViewはこのViewControllerの基本Viewとなります。
その上に地図用のMKMapViewを重ねます。
後から地図の領域を狭くして他のViewを載せたりするためにわざと別にしてあります。
[cce_objc]- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 表示範囲/中心座標の設定
MKCoordinateSpan span = MKCoordinateSpanMake(0.005f, 0.005f);
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(35.658704f, 139.745408f);
MKCoordinateRegion region = MKCoordinateRegionMake(coordinate, span);
[mapView setRegion:region animated:NO];
}[/cce_objc]
-[UIView viewWillAppear:]で地図の表示状態を設定します。
MKMapViewは-[MKMapView setRegion:animated:]で地図の表示範囲を設定できます。
MKCoordinateRegion構造体で表示領域と中心座標を指定します。
animated:NOならばぱっと切り替わり、animated:YESならばスクロールします。
MKCoordinateRegion構造体は表示領域を表すspan(MKCoordinateSpan構造体)と中心座標を示すcenter(CLLocationCorrdinate2D構造体)を持ちます。
MKCoordinateSpan構造体はMKCoordinateSpanMake関数で作成します。第1引数が緯度(latitude)方向の表示範囲、第2引数が経度(longitude)方向の表示範囲で、単位はdegree(1度=約111.2km)です。ここで指定した範囲を含む領域が画面に表示されます。
緯度が高いと経度方向の1度あたりの距離は短くなるけど反映するんだろうか・・・?
CLLocationCoordinate2D構造体はCLLocationCoordinate2DMake関数で作成します。引数は第1引数が緯度(latitude)、第2引数が経度(longitude)です。
緯度(latitude)は北緯がプラス、南緯がマイナスの値を取ります。
経度(longitude)は東経がプラス、西経がマイナスの値を取ります。
[cce_objc]- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
– (void)dealloc {
[mapView release];
[super dealloc];
}
@end[/cce_objc]
あとはお約束ですね。
中心座標を東京タワーの座標にしたので、きちんと表示されていますね。
次回はAndroidで同様の画面をつくるところまでを説明する予定です。