2011年5月5日

iOS SDK with MapKit (Google Map) 練習 (1)

Hi all,最近練習了在iOS終始用Google Map,有一些成果後筆記一下順便分享給大家,這次要來分享如何使用 iOS SDK 的 MapKit framework來建立地圖,並且在地圖上建立幾個點,還有一些相關的運用;至於查詢地指方面的功能,就等我試出來後再跟大家介紹吧。

我會將閱讀文章的人視作對 c / obj-c 以及 iOS有一定的認識,因此在obj-c/c的一些使用內容將不會有太多的解釋。


首先,先在專案(我專案命為MapKit_Practice)內加入MapKit framework,你可以參考下圖來增加需要的framework

增加完成後,接著我們開始建立Google Map到我們的畫面上
MapKit_PracticeViewController.h
#import <MapKit/MapKit.h>
@interface MapKit_PracticeViewController : UIViewController {
    MKMapView *mapView;
}
@end
接的修改MapKit_PracticeViewController.m
#import "MapKit_PracticeViewController.h"
@implementation MapKit_PracticeViewController
- (void)dealloc
{
    [mapView release];
    [super dealloc];
}
-(void)loadView
{
    [super loadView];
    mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    [self.view addSubview:mapView];
}
執行結果

到這邊就完成基本的建立了,但是我們並不想要把地圖一開始顯示的地點設在美國,我想把他設定在台北火車站的附近,所以我們接著修改map.region參數:
MapKit_PracticeViewController.m
-(void)loadView
{
    [super loadView];
    mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    MKCoordinateRegion region;
    region.center.latitude = 25.044;
    region.center.longitude = 121.526;
    MKCoordinateSpan span;
    span.latitudeDelta  = .002;
    span.longitudeDelta = .002;
    region.span = span;
    [mapView setRegion:region animated:YES];
    [self.view addSubview:mapView];
}
上面的程式碼中我們先宣告了一個 MKCoordinateRegion 結構的變數 region,並將中心點設定在(北緯,東經):
(25.044,121.526)的地方,接著在設定地圖縮放的等級(zoom-level) MKCoordinateSpan span,數值越小呈現的地圖範圍越小。
執行的結果如下圖

到這邊,我們已經建立了基本的地圖內容,被並且將起始位置跟縮放等級設定在我們所想要的位置,接下來我們將要在地圖增加一個地點網路基因,這要用到MKAnnotation Protocal,這個協定被宣告如下:
@protocol MKAnnotation <NSObject>

// Center latitude and longitude of the annotion view.
// The implementation of this property must be KVO compliant.
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@optional

// Title and subtitle for use by selection UI.
- (NSString *)title;
- (NSString *)subtitle;

// Called as a result of dragging an annotation view.
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);

@end
上面的程式碼,你應該有注意到並沒有我們在宣告Class時候都會出現一個@interface ClassName {}的內容,因此我們需要去宣告一個 Class 來採用並實現這個資料模型(data medol)。
註解在地圖上的資訊(Annotations)是由MKAnnontation 跟 MKAnnontationView組成

宣告一個新的Class Annotation
//Annotation.h:
#import <MapKit/MapKit.h>
@interface Annotation : NSObject <MKAnnotation> {
}
@end
//Annotation.m:
-(NSString*)title
{
    return @"網路基因";
}
-(NSString*)subtitle
{
    return @"電話:02-2395-5378";
}
-(CLLocationCoordinate2D) coordinate
{
    CLLocationCoordinate2D _coordinate = {25.044423,121.52673};
    return _coordinate;
}
接著我們直接使用Annotation這個類別並增加到我們的地圖上
//MapKit_PracticeViewController.h
#import Annotation.h
//MapKit_PracticeViewController.m
-(void)loadView
{
    [super loadView];
    mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    MKCoordinateRegion region;
    region.center.latitude = 25.044;
    region.center.longitude = 121.526;
    MKCoordinateSpan span;
    span.latitudeDelta  = .0015;
    span.longitudeDelta = .0015;
    region.span = span;
    [mapView setRegion:region animated:YES];

    Annotation *myAnnotation = [[Annotation alloc] init];
    [mapView addAnnotation:myAnnotation];

    [self.view addSubview:mapView];
}
執行後的畫面(我有先點擊大頭針)如下

這樣我們就成功的在地圖上增加了一個地點"網路基因",但是現在的Annotation class在使用上非常的不方便,所以我在針對Annotation做一些修改以便在使用尚可以更符合我們的需求
//Annotation.h:
#import <MapKit/MapKit.h>

@interface Annotation : NSObject <MKAnnotation> {
    NSString *_title;
    NSString *_subTitle;
    CLLocationCoordinate2D _coordiante2D;
}

@property (nonatomic , readonly) NSString *title;
@property (nonatomic , readonly) NSString *subtitle;
@property (nonatomic , readonly) CLLocationCoordinate2D coordinate;

-(id) initWhithTitle:(NSString *) theTitle subTitle:(NSString *)theSubTitle andCoordiante:(CLLocationCoordinate2D) theCoordinate;
@end

//Annotation.m:
@implementation Annotation
//設定getter
@synthesize title=_title,subtitle=_subTitle,coordinate=_coordiante2D;

-(void)dealloc
{
    [_title release];
    [_subTitle release];
    [super dealloc];
}

-(id) initWhithTitle:(NSString *) theTitle subTitle:(NSString *)theSubTitle andCoordiante:(CLLocationCoordinate2D) theCoordinate
{
    self = [super init];
    if (self) {
        _title = [theTitle copy];
        _subTitle = [theSubTitle copy];
        _coordiante2D = theCoordinate;
    }
    return self;
}
然後,除了原來的網路基因外,我希望在另外增加兩個資訊在地圖上,接著修改
//MapKit_PracticeViewController.m
-(void)loadView
{
    [super loadView];
    mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    MKCoordinateRegion region;
    region.center.latitude = 25.044;
    region.center.longitude = 121.526;
    MKCoordinateSpan span;
    span.latitudeDelta  = .0015;
    span.longitudeDelta = .0015;
    region.span = span;
    [mapView setRegion:region animated:YES];

    CLLocationCoordinate2D location0 = {25.044423,121.52673};
    Annotation *myAnnotation0 = [[Annotation alloc] initWhithTitle:@"網路基因資訊股份有限公司"
                                                          subTitle:@"電話:02-23955378" 
                                                     andCoordiante:location0];
    CLLocationCoordinate2D location1 = {25.04411,121.52534};
    Annotation *myAnnotation1 = [[Annotation alloc] initWhithTitle:@"遠東國際商業銀行" 
                                                          subTitle:@"電話:02-2327-8898" 
                                                     andCoordiante:location1];
    CLLocationCoordinate2D location2 = {25.04443,121.52579};
    Annotation *myAnnotation2 = [[Annotation alloc] initWhithTitle:@"文化大學推廣教育部" 
                                                          subTitle:@"電話:02-2356-7356" 
                                                     andCoordiante:location2];
    
    [mapView addAnnotations:[NSArray arrayWithObjects:myAnnotation0, myAnnotation1, myAnnotation2, nil]];
    [myAnnotation0 release];
    [myAnnotation1 release];
    [myAnnotation2 release];

    [self.view addSubview:mapView];
}
執行後的結果如下

將Annotation Class修改後,使用起來會更方便,在增加新的資訊的時候也不用一個Class宣告一個資訊造成之後的管理不方便;關於MKAnnotionView以及MKMapDelegate的部份因為內容好像有點太長了,所以就不在這篇繼續下去了,會在下一篇的練習中在分享給大家。

最後希望這篇內容可以對大家有幫助,對於文章內容有錯誤或者建議的地方,也請大家多多指教,謝謝。

參考內容:
Introduction to MapKit on iOS Tutorial Link
Map Kit Framework Reference Link
MKMapView Class Reference Link
MKAnnotation Protocol Reference Link

6 則留言:

  1. 你好﹐

    可以提供程式碼下載嗎﹖ 一直找不到問題出在哪裡!!!

    回覆刪除
  2. 不好意思,這陣子比較忙
    如果還有需要檔案可以寄信給我

    回覆刪除
  3. 你好﹐
    可以提供程式碼嗎?
    因為我有些地方還是不太懂,謝謝噢!!
    我的EMAIL:newboys.tw@yahoo.com.tw

    回覆刪除
  4. 你好 可以請問一下如果要顯示目前裝置所在的位置
    座標那邊應該要怎麼改才能抓到目前裝置的座標呢?
    在網路上有查到使用 showsUserLocation可是不知道怎麼用

    麻煩你了 感謝~!!

    回覆刪除
  5. Hi Henry
    showsUserLocation會傳回MKAnnotation Protocol的物件
    你可以去取得他的coordinate 參數,就可以得到他的緯經度囉

    不好意思這麼晚才回復

    回覆刪除
  6. 請問要如何讓大頭針一開始放入地圖時就自動顯示文字呢?

    回覆刪除