高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

iPhone app 實作練習 - 幫你的地圖 app 加上大頭針

image

前面幾篇有提到一些@category@progocol,還有一些記憶體管理的東西,我自己也看得頭很花,不過看一堆的理論還不如直接實作來得快。所以,接下來我們就來把前面那個陽春的地圖功能,加上一些註解或大頭針的功能,讓整個畫面看起來豐富、實用一些。

首先,我想要做的效果是在地圖上加個大頭針跟註解,如下圖:

image

做法就是在原來的MapView上加上一個註解(Annotation),讓MapView把它畫出來。要注意的是,Annotation本身不一種View,所以不是看得到的元件,不會直接在畫面上看得到。Annotation類別只是描述一些資料,例如title、subtitle,加到MapView之後,有個叫做MKAnnotationView的類別幫我們畫出來的。而把annotation加到MapView的語法是:

1
[map_view addAnnotation:(id <MKAnnotation>)annotation]

這可以讓你一次加一個Annotation到MapView裡,如果你要一次加多個大頭針進去,則可使用addAnnotations,後面接一個NSArray,裡面裝你要標示的Annotation即可。如果要移掉,則是使用removeAnnotation,如果要移掉多個則是使用removeAnnotations,詳細使用方法可再請參考使用手冊。

回來看上面那行,希望你還記得protocol的東西,如果不記得的話請再看一下這篇複習一下,那行的意思就是說addAnnotation方法後面接的參數必須是個有實作MKAnnotation這個protocol的物件。但是Cocoa Touch並沒有內建Annotation的類別可以直接塞給它,我是滿好奇這麼常用的功能為什麼不直接就內建進來,直接new一個來用就好了。不過沒關係,沒有的話我們就自己手動刻一個。

首先,先在Classes裡新增一個Objective-C class檔案,我把它命名為MyCompany(.m跟.h),然後我的Classes群組看起來會像這樣:

image

再來,修改一下MyCompany.h裡的@interface,讓它實作自MKAnnotation protocol:

1
2
3
4
5
6
7
8
9
10
// 檔案:MyCompany.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MyCompany : NSObject <MKAnnotation>
{

}

@end

好了,然後呢? 要實作哪些方法要怎麼看? 在MKAnnotation上按滑鼠右選,選擇”find text in documentation”,它會去找到這個protocol的相關詳細說明。但我個人會更偏好在MKAnnotation上按住command鍵加上double click,它會跳到這個protocol的定義,直接看原始碼是最快的。MKAnnotation這個protocol的定義如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>

@protocol MKAnnotation <NSObject>

// Center latitude and longitude of the annotion view.
@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

從定義看來,實作這個protocol只需要實作做coordinate這個getter就行了,其它的都是optional的。但因為我想要在大頭針上面加上註解說明,所以需要再實作title跟subtitle的setter,程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 檔案:MyCompany.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MyCompany : NSObject <MKAnnotation>
{
  CLLocationCoordinate2D coordinate;
  NSString *title;
  NSString *subtitle;
}

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

@end

骨架好了,再來跳到MyCompany.m,把肉填起來:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 檔案:MyCompany.m
#import "MyCompany.h"

@implementation MyCompany

@synthesize coordinate;
@synthesize title;
@synthesize subtitle;

-(id) initWithCoordinate: (CLLocationCoordinate2D) the_coordinate
{
  if (self = [super init])
  {
    coordinate = the_coordinate;
  }
  return self;
}

-(void) dealloc
{
  self.title = nil;
  self.subtitle = nil;
  [super dealloc];
}

@end

前面幾行的@synthesize是對應到@property用的,這裡唯一比較長的程式碼是initWithCoordinate,這是個委任的建構子,用來在init的時候把coordinate也一併傳進來。

OK! 到這裡的前置工作已經完成了,接著要把它併到之前那個範例的程式碼裡了,首先別忘了要先把MyCompany.h給import進來:

1
#import MyCompany.h

再來一樣直接偷懶的把程式碼全部寫在viewDidLoad裡面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- (void)viewDidLoad
{
  // 建立一個CLLocationCoordinate2D
  CLLocationCoordinate2D mylocation;
  mylocation.latitude = 25.01141;
  mylocation.longitude = 121.42554;

  // 建立一個region,待會要設定給MapView
  MKCoordinateRegion kaos_digital;

  // 設定經緯度
  kaos_digital.center = mylocation;

  // 設定縮放比例
  kaos_digital.span.latitudeDelta = 0.003;
  kaos_digital.span.longitudeDelta = 0.003;

  // 準備一個annotation
  MyCompany *mycompany = [[[MyCompany alloc] initWithCoordinate:mylocation] autorelease];
  mycompany.title = @"高思數位網路";
  mycompany.subtitle = @"媽,我在這裡啦!";

  [map_view setRegion:kaos_digital];

  // 把annotation加進MapView裡
  [map_view addAnnotation:mycompany];

  [super viewDidLoad];
}

上面這段程式碼是從前面那篇借來用的。做到這裡,按下Build and Run,應該就可以看到有一根紅色的大頭針定在畫面上:

image

再點一下大頭針就會跳出說明:

image

其實MKAnnotationView能做的變化還不少,例如變更大頭針的樣式、顏色,或是在註解的左邊或右邊加上按鈕,按下按鈕之後會執行其它的事情(callout),更詳細的說明可再參考Apple的官方手冊,地圖在行動裝置上能做的應用還挺多的,大家可以再想想怎麼拼裝組合囉 :)

原始檔下載

建議閱讀:

iOS Reference Library – MKAnnotationView

Comments