/* syntax highlight */ /* end of syntax highlight */

2011年1月25日 星期二

iphone app 開發 (四十) Core Location 地理位置資訊偵測

Bookmark and Share

手機這種新的界面,能夠給予我們全新的軟體應用方式

其中一個很大的特色就是「地理資訊」,就像我們平常使用的 Google Map 一類的服務

本篇文章將會介紹如何抓到我們自身的地理資訊 (使用 GPS)

至於進一步的 App 應用就要靠讀者發揮了

螢幕快照 2011-01-26 下午12.08.10

程式碼來源參考自 探索 iPhone 程式開發實戰 一書

書中有更詳細的解釋,建議可以直接買書來看

 

整個 App 的邏輯是,我們必須先建立一個位置管理程式 (Location Manager),再來利用此管理程式與 Core Location 互動,

 

 

步驟一:專案設定

請選 View-based Application

螢幕快照 2011-01-26 上午10.45.29

 

取專案名稱,我取叫 location

螢幕快照 2011-01-26 上午10.45.47

 

因為我們會用到地理資訊,所以需要把 CoreLocation framework 給抓進來

螢幕快照 2011-01-26 上午11.30.46螢幕快照 2011-01-26 上午11.30.59  

 

 

步驟二:撰寫程式碼

首先是 header 部份,此部份主要是宣告了一個 locationManager 的實例,以及一個 location 的實例,其他的都只是負責呈現資訊的 UILabel 變數,程式碼如下:

 

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h> //引入標頭檔

@interface locationViewController : UIViewController <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;
    CLLocation *start; //記錄開始的地方, 以計算出移動距離
    UILabel *latitudeLabel; //緯度
    UILabel *longitudeLabel; //經度
    UILabel *horizontalAccuracyLabel; //水平準確度
    UILabel *altitudeLabel; //高度
    UILabel *verticalAccuracyLabel; //高度準確度
    UILabel *distanceTraveledLabel; //移動的距離
}

@property (retain,nonatomic) CLLocationManager *locationManager; // location manager 實例
@property (retain,nonatomic) CLLocation *start; //location 實例

//label 部份都只是為了宣告呈現資訊的接口
@property (retain,nonatomic) IBOutlet UILabel *latitudeLabel;
@property (retain,nonatomic) IBOutlet UILabel *longitudeLabel;
@property (retain,nonatomic) IBOutlet UILabel *horizontalAccuracyLabel;
@property (retain,nonatomic) IBOutlet UILabel *altitudeLabel;
@property (retain,nonatomic) IBOutlet UILabel *verticalAccuracyLabel;
@property (retain,nonatomic) IBOutlet UILabel *distanceTraveledLabel;

@end

 

 

接下來是實做檔 location.m ,此部份稍稍複雜一點,

第一部分當然是先 synthesize 宣告的變數

#import "locationViewController.h"

@implementation locationViewController

@synthesize locationManager;
@synthesize start;
@synthesize latitudeLabel;
@synthesize longitudeLabel;
@synthesize horizontalAccuracyLabel;
@synthesize altitudeLabel;
@synthesize verticalAccuracyLabel;
@synthesize distanceTraveledLabel;

 

 

再來是設定一開始就需要載入的程式碼,像是起始化 locationManager ,剛開始需要指定一些參數,其中比較特別要提的是 locationManager.desiredAccuracy = kCLLocationAccuracyBest 指的是選擇最精確的方法,其他還有 kCLLocationAccuracyNearestTenMeters、kCLLocationAccuracyHundredMeters、kCLLocationAccuracyKilometer 等等,其他方法可能較不精確,但也許比較不耗手機的資源。

- (void)viewDidLoad {
    self.locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self; //指定委派
    locationManager.desiredAccuracy = kCLLocationAccuracyBest; //指定精確程度
    locationManager.distanceFilter = 1000.0f; //表示設定當移動1000公尺才執行一次位置管理
    [locationManager startUpdatingLocation]; //只要偵測到位置的變更大於 1000 公尺時,啟動位置管理程式
}

 

 

然後記得設定解除記憶體使用的情況,即改變 viewDidUnload 與 dealloc 方法之內容

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.locationManager = nil;
    self.latitudeLabel = nil;
    self.longitudeLabel = nil;
    self.horizontalAccuracyLabel = nil;
    self.altitudeLabel = nil;
    self.verticalAccuracyLabel = nil;
    self.distanceTraveledLabel = nil;
    [super viewDidUnload];
}

- (void)dealloc {
    [locationManager release];
    [start release];
    [latitudeLabel release];
    [longitudeLabel release];
    [horizontalAccuracyLabel release];
    [altitudeLabel release];
    [verticalAccuracyLabel release];
    [distanceTraveledLabel release];
    [super dealloc];
}

 

 

再來是重要的實做 locationManager 函式部份,每一段的部份我都有寫註解,直接參考即可

//此方法會接受三項參數,第一個 manager 就是位置管理程式,newLocation 是定義目前位置的,oldLocation 則是前一次更新的位置
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
    if(start ==nil){ //如果是第一次抓取,則設定此點為 newLocation
        self.start = newLocation;
    }
    //利用 newLocation.coordinate.latitude 來抓到緯度資訊,且在後面加上一個  ° ,可按
    NSString *latitudeString = [[NSString alloc] initWithFormat:@"%g°",newLocation.coordinate.latitude];
    latitudeLabel.text = latitudeString;
    [latitudeString release];
    //利用 newLocation.coordinate.longitude 來抓到經度資訊
    NSString *longtitudeString = [[NSString alloc] initWithFormat:@"%g°",newLocation.coordinate.longitude];
    longitudeLabel.text = longtitudeString;
    [longtitudeString release];
    // 抓到水平精準度
    NSString *horizontalAccuracyString = [[NSString alloc] initWithFormat:@"%gm",newLocation.horizontalAccuracy];
    horizontalAccuracyLabel.text = horizontalAccuracyString;
    [horizontalAccuracyString release];
    // 抓到高度
    NSString *altitudeString = [[NSString alloc] initWithFormat:@"%gm",newLocation.altitude];
    altitudeLabel.text = altitudeString;
    [altitudeString release];
    // 抓到高度精準度
    NSString *verticalAccuracyString = [[NSString alloc] initWithFormat:@"%gm",newLocation.verticalAccuracy];
    verticalAccuracyLabel.text = verticalAccuracyString;
    [verticalAccuracyString release];
    // 用 distanceFormLocation 判斷 newLocation 與 start 之間的距離,並顯示在 label 上
    CLLocationDistance distance = [newLocation distanceFromLocation:start];
    NSString *distanceString = [[NSString alloc] initWithFormat:@"%gm",distance];
    distanceTraveledLabel.text = distanceString;
    [distanceString release];
}

 

 

最後則是如果使用者拒絕去提供它的地理資訊呢 ? 這時 Core Location 會呼叫委派方法 didFailWithError ,如果使用者選擇拒絕,則錯誤訊息會丟出 kCLErrorDenied 錯誤碼,如果是改丟 kCLErrorLocationUnknown,則只是表示這個錯誤是暫時的,之後就會被修復。至於後半部的 alert 大家應該很熟了,所以這邊就不特別去提它。

-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    NSString *errorType = (error.code == kCLErrorDenied) ? @"Access Denied" : @"Unknow Error";
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"error getting location" message:errorType delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

 

 

 

步驟三:安排畫面元素

程式部份完成了,則我們可以開始安排畫面,畫面很簡單,總共就是 12 個 label ,你先照著下面的結果去擺 12 個 label ,左邊那 6 個則改成需要的資訊,右邊 6 個則把內容刪除,然後就照以前學的設定 IBOutlet 方法,從 File’s Owner 拉線到右邊那 6 個 label 上面,應該會出現相關的 UILabel 可以選擇,依序對應上去即可。

  螢幕快照 2011-01-26 下午3.38.47

 

此為File’s Owner 的 Outlet 設定,下圖是完成後的畫面。

螢幕快照 2011-01-26 下午3.36.01

 

 

步驟四:編譯執行

如果程式沒有問題,你應該會看到以下畫面,App 會先詢問是否要分享你的地理資訊

如果回答是,就會把相關資訊呈列出來,如果否,則會跳出一個 alert 告訴你說 access denied.

如此一來你就完成一個抓到地理資訊的簡單小 App

 

螢幕快照 2011-01-26 下午12.08.10 螢幕快照 2011-01-26 下午12.09.34

 

 
參考資料部份有我在網路上看到的相關資訊,該範例 已經可以完成到抓自己的 location data 並顯示在 google map 上面,有空我再研究看看分享給大家。

 

 

參考資料

探索 iPhone 程式開發實戰

iPhone SDK 3.0 – Playing with Map Kit

iPhone SDK 3.0 – Playing with Map Kit – Part 2

iPhone SDK 3.0 – Playing with Map Kit – Part 3

0 意見:

張貼留言

Related Posts Plugin for WordPress, Blogger...