【IT168 技術文檔】如今,配備GPS功能的行動裝置越來越普遍了,使用GPS定位系統,可以精確地定位你當前所在的地理位置,但由於GPS接收機需要對準天空才能工作,因此在室內環境基本無用。
另一個找到自己所在位置的有效方法是使用手機基站,手機開機時,它會與周圍的基站保持聯繫,如果你知道這些基站的身份,就可以使用各種資料庫(包含基站的身份和它們的確切地理位置)計算出手機的物理位置。基站不需要衛星,和GPS不同,它對室內環境一樣管用。但它沒有GPS那樣精確,它的精度取決於基站的密度,它在基站密集型區域的準確度最高。
提示:第一代iPhone並沒有配置GPS接收器,基站方式不能應用到iPod Touch上,因為它不是手機。
第三種方法是依賴Wi-Fi,使用這種方法時,設備連接到Wi-Fi網絡,通過檢查服務提供商的數據確定位置,它既不依賴衛星,也不依賴基站,因此這個方法對於可以連接到Wi-Fi網絡的區域有效,但它的精確度也是這三個方法中最差的。
定位框架內核
在iPhone上,蘋果提供了定位框架內核,以幫助你確定你的物理位置,這個框架的美妙之處在於它使用了前面提到的所有三種方法,具體使用的是哪種方法對於開發者來說是透明的,開發人員只需要指定所需要的精度,定位內核將會以最佳方式確定定位結果。
你一定感到很吃驚吧?!本文其餘部分將向你展示這是如何做到的。
獲取位置坐標
使用Xcode,創建一個新的基於視圖的應用程式項目,取名為LBS,在新項目中,雙擊LBSViewController.xib文件,在界面設計工具中編輯它。使用下面的組件填充視圖窗口,如圖1所示。
l Label
l TextField
圖 1 位置視圖實例:用Label和TextFiled填充這個窗口
在Xcode中框架組上點擊右鍵,選擇「添加」*「現有框架」,選擇「Framework/CoreLocation.framework」,向LBSViewController.h文件中添加以下粗體字顯示的代碼:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface LBSViewController : UIViewController
<CLLocationManagerDelegate> {
IBOutlet UITextField *latitudeTextField;
IBOutlet UITextField *longitudeTextField;
IBOutlet UITextField *accuracyTextField;
CLLocationManager *lm;
}
@property (retain, nonatomic) UITextField *latitudeTextField;
@property (retain, nonatomic) UITextField *longitudeTextField;
@property (retain, nonatomic) UITextField *accuracyTextField;
@end
若要使用CLLocationManager類,需要在你的視圖控制器類中實現CLLocationManagerDelegate協議,還需要創建三個出口用於連接視圖窗口中的三個TextFiled視圖。
回到界面編輯器,單擊並拖動文檔的所有者項目到三個TextField視圖,然後分別選擇latitudeTextField,longitudeTextField和accuracyTextField。
在LBSViewController.m文件中查詢以下代碼中的粗體部分:
#import "LBSViewController.h"
@implementation LBSViewController
@synthesize latitudeTextField, longitudeTextField, accuracyTextField;
- (void) viewDidLoad {
lm = [[CLLocationManager alloc] init];
if ([lm locationServicesEnabled]) {
lm.delegate = self;
lm.desiredAccuracy = kCLLocationAccuracyBest;
lm.distanceFilter = 1000.0f;
[lm startUpdatingLocation];
}
}
- (void) locationManager: (CLLocationManager *) manager
didUpdateToLocation: (CLLocation *) newLocation
fromLocation: (CLLocation *) oldLocation{
NSString *lat = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.latitude];
latitudeTextField.text = lat;
NSString *lng = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.longitude];
longitudeTextField.text = lng;
NSString *acc = [[NSString alloc] initWithFormat:@"%g",
newLocation.horizontalAccuracy];
accuracyTextField.text = acc;
[acc release];
[lat release];
[lng release];
}
- (void) locationManager: (CLLocationManager *) manager
didFailWithError: (NSError *) error {
NSString *msg = [[NSString alloc]
initWithString:@"Error obtaining location"];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Error"
message:msg
delegate:nil
cancelButtonTitle: @"Done"
otherButtonTitles:nil];
[alert show];
[msg release];
[alert release];
}
- (void) dealloc{
[lm release];
[latitudeTextField release];
[longitudeTextField release];
[accuracyTextField release];
[super dealloc];
}
前面的代碼創建了CLLocationManager類的一個實例,在使用對象之前,你應該檢查用戶是否開啟了設備的定位服務,如果開啟了,你可以使用desiredAccuracy屬性指定想要的精度,使用下面的常量指定想要的精度:
l kCLLocationAccuracyBest
l kCLLocationAccuracyNearestTenMeters
l kCLLocationAccuracyHundredMeters
l kCLLocationAccuracyKilometer
l kCLLocationAccuracyThreeKilometers
distanceFilter屬性讓你指定設備必須移動多少距離位置信息才會更新,這個屬性的單位是米。如果你想得到所有移動的通知,可以使用kCLDistanceFilterNone常量,最後,使用startUpdatingLocation方法啟動位置管理器。
要獲得位置信息,需處理下面兩個事件:
l locationManager:didUpdateToLocation:fromLocation:
l locationManager:didFailWithError:
當獲得一個新的定位值時,設備觸發locationManager:didUpdateToLocation:fromLocation:事件,如果位置管理器不能確定位置信息,就會觸發locationManager:didFailWithError:事件。
當設備可以確定位置時,你可能想顯示經緯度值和精度,這時你可以使用CLLocation對象,它的horizontalAccuracy屬性可以指定精度範圍,單位是米。
按Command-r在iPhone模擬器上測試該程序,圖2顯示了模擬器顯示的位置經緯度值,同時顯示了精度。
圖 2 定位測試:當你在iPhone模擬器上測試該示例程序時,總會顯示這些固定的值