參考IOS 定位範例:
1.
iPhone開發實戰:定位與地圖
2.
GPS 衛星定位展示範例
實作IOS定位服務
關於定位服務,IOS中已經提供二個framwork給開發者使用:
1.
CoreLocation.framework:
n (CLLocationManager類別)定位-獲得經緯度。
2. MapKit.framework:
n (MKReverseGeocoder
類別)當前的經緯度所對應的地理位置資訊是什麼。
n (MKAnnotationView類別)把取到的經緯度資訊顯示到地圖上
在Xcode新建專案:
在.h檔裡要宣告這是一個符合MKMapViewDelegate, MKReverseGeocoderDelegate, CLLocationManagerDelegate Protocal的類別。
1. MKMapViewDelegate:委派代理地圖呈現
2. MKReverseGeocoderDelegate:委派理取得地理位置資訊
3. CLLocationManagerDelegate:委派代理取得當前的經緯度。
LocationViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <CoreLocation/CLLocationManagerDelegate.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKReverseGeocoder.h>
@interface LocationViewController : UIViewController<MKMapViewDelegate, MKReverseGeocoderDelegate, CLLocationManagerDelegate> {
CLLocationManager *locmanager;
MKMapView *mapView;
}
@end
在.m檔裡要實作定位服務的功能,記得將delegate設為self,程式碼如下:
LocationViewController.m
#import "LocationViewController.h"
#import "DemoAnnotation.h"
@interface LocationViewController ()
@end
@implementation LocationViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 加入MKMapView 的物件,可呈現地圖上的所有資訊。
mapView=[[MKMapView alloc] initWithFrame:self.view.frame];
mapView.delegate=self;
[self.view insertSubview:mapView atIndex:0];
// CLLocationManager 物件,startUpdatingLocation 可以
locmanager = [[CLLocationManager alloc] init];
[locmanager setDelegate:self];
[locmanager setDesiredAccuracy:kCLLocationAccuracyBest];
//透過呼叫startUpdatingLocation開啟定位功能,然後使用stopUpdatingLocation停止定位,其中定位資訊是通過loctionManager:didUpdateToLocation
[locmanager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// newLocation是新偵測到的地理位置,針對此地設定區域範圍
MKCoordinateRegion region;
region.center=newLocation.coordinate;
//使用 Span 設定地圖的縮放。
MKCoordinateSpan span;
span.latitudeDelta=.005;
span.longitudeDelta=.005;
region.span=span;
[mapView setRegion:region animated:TRUE];
// DemoAnnotation是繼承MKAnnotation的自訂類別,稍後會提到,可以記錄關於此座標點的相關資訊,像主題及副標題。
DemoAnnotation *annotation = [[DemoAnnotation alloc] initWithCoordinate:newLocation.coordinate];
// 將座標資訊加入地圖
[mapView addAnnotation:annotation];
//
// 若不想用自訂的格式可以直接使用MKReverseGeocoder類別,如下:
MKReverseGeocoder
*geocoder=[[MKReverseGeocoder alloc]
initWithCoordinate:newLocation.coordinate];
geocoder.delegate=self;
[geocoder start];
*/
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
}
這裡先補充newLocation表示最新定位,oldLocation表示上一次的定位資訊。這兩個都是CLLocation對象。以下是CLLocation的屬性說明:
altitude 海拔高度
coordinate 經緯度
course 行駛方向
horizontalAccuracy 水準方向的精確度
Speed 行駛速度
timestamp 時間戳記
verticalAccuracy 垂直方向的精確度
coordinate 經緯度
course 行駛方向
horizontalAccuracy 水準方向的精確度
Speed 行駛速度
timestamp 時間戳記
verticalAccuracy 垂直方向的精確度
承didUpdateToLocation事件的處理,若不想用自訂的格式,是使用MKReverseGeocoder類別,就要實作didFindPlacemark及didFailWithError,可以取得經緯度的地理資訊,例如:國家、郵地區號..。
關於MKPlacemark 可以參考IOS - CLPlacemark Class Reference:http://developer.apple.com/library/ios/#DOCUMENTATION/CoreLocation/Reference/CLPlacemark_class/Reference/Reference.html
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark{
NSLog(@"\n
country:%@\n postalCode:%@\n ISOcountryCode:%@\nlocality:%@\n subLocality:%@\n
administrativeArea:%@\nsubAdministrativeArea:%@\n thoroughfare:%@\n
subThoroughfare:%@\n",
placemark.country,
placemark.postalCode,
placemark.ISOcountryCode,
placemark.administrativeArea,
placemark.subAdministrativeArea,
placemark.locality,
placemark.subLocality,
placemark.thoroughfare,
placemark.subThoroughfare);
// 將座標資訊加入地圖
[mapView addAnnotation:placemark];
}
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder
didFailWithError:(NSError*)error{
NSLog(@"reverse
geocoder fail!!");
}
[地圖顯示] - 如何把取到的經緯度資訊顯示到地圖上呢?其實每個座標資訊在地圖中顯示後都對應一個MKAnnotationView,而MKAnnotationView又負責解析了一個實現MKAnnotation協定的資料物件。因此我們首先要做的事情就是把取到的經緯度轉換為MKAnnotation協定物件。先定義一個實現MKAnnotation協議的類:
DemoAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface DemoAnnotation : NSObject<MKAnnotation> {
CLLocationCoordinate2D _coordinate;
}
-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end
DemoAnnotation.m
#import "DemoAnnotation.h"
@implementation DemoAnnotation
@synthesize coordinate=_coordinate;
-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate{
if(self = [super init]) {
_coordinate=coordinate;
}
return self;
}
-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate{
_coordinate=newCoordinate;
}
-(NSString*)title{
return @"我的位置";
}
-(NSString*)subtitle{
return @"Peggy haha";
}
@end
呼叫[mapView addAnnotation:XXX] 會實作mapView 協定中的 viewForAnnotation
及didReceiveMemoryWarning 。
viewForAnnotation這個方法,這是MKMapView實際建立座標點的地方。MKMapView類別在render地圖的時候會依照Annotation集合的資料建立座標點。
Annotation集合中有幾筆資料vieForAnnotation方法就會被執行幾次。因此每次viewForAnnotation被執行,我們都要建立一個MKAnnotationView物件的實體,並且return這個實體。
MKMapView接收到MKAnnotationView的實體就會將它顯示在地圖上,這就是我們想要顯示在地圖上的座標點。在上面程式碼中使用了
MKPinAnnotationView這個物件是繼承自MKAnnotationView,作用就是在地圖上顯示一個大頭釘。
LocationViewController.m
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation{
NSString*annotationViewId=@"CurrentUserAnnotationView";
MKPinAnnotationView *annotationView=
(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationViewId];
if(annotationView==nil)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationViewId];
//地圖上的大頭針自訂格式
annotationView.image = [UIImage imageNamed:[NSString stringWithFormat:@"12.png"]];
annotationView.draggable = NO;
//annotationView.animatesDrop = YES; //->目前只有預設的大頭針才有動畫效果。
//設定在點選大頭釘的時候氣泡視窗是否會談出來。
annotationView.canShowCallout = YES;
//設定右邊的箭頭鈕及事件
UIButton *button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView=button;
//設定左邊的小圖示及事件
UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
[leftButton setImage:[UIImage imageNamed:@"star.png"] forState:UIControlStateNormal];
[leftButton addTarget:self
action:@selector(checkButtonTapped:event:)
forControlEvents:UIControlEventTouchUpInside];
annotationView.leftCalloutAccessoryView = leftButton;
}
return annotationView;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)checkButtonTapped:(id)sender event:(id)event{
UIAlertView *tmp= [[UIAlertView alloc] initWithTitle:@"訊息!" message:@"Peggy測試" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[tmp show];
}
程式執行結果:
Hi there Dear, are you really visiting this website on a regular basis, if
回覆刪除so afterward you will without doubt take fastidious knowledge.
My web-site http://liverwiki.hupo.org.cn
Thanks for the marvelous posting! I certainly enjoyed reading it, you are
回覆刪除a great author.I will make certain to bookmark your blog and may
come back very soon. I want to encourage you to continue your
great job, have a nice afternoon!
Feel free to visit my site ... es.jaykodesign.com