iOS中有三個定位服務組件:
?? Wifi定位,通過查詢一個Wifi路由器的地理位置的信息。比較省電,iPod touch和iPad也可以采用。
?? 蜂窩基站定位,通過移動運用商基站定位。也適合有3G版本的iPod touch和iPad。
?? GPS衛星定位,通過3-4顆GPS定位位置定位,最為準確,但是耗電量大,不能遮擋。
Core Location
Core Location是iPhone、iPad等開發定位服務應用程序的框架。我們要在Xcode中添加“CoreLocation.framework”存在的框架。
主要使用的類是:CLLocationManager,通過CLLocationManager實現定位服務。
CoreLocation.framework
定位服務實例
項目WhereAmI:
WhereAmIViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController<CLLocationManagerDelegate>
{CLLocationManager*
locationManager;
}@property (strong, nonatomic) CLLocationManager*
locationManager;
@property (retain, nonatomic) IBOutlet UILabel *
longitudeText;
@property (retain, nonatomic) IBOutlet UILabel *
latituduText;
@property (retain, nonatomic) IBOutlet UIActivityIndicatorView *
activity;
- (IBAction)findMe:(
id)sender;
- (IBAction)webMap:(
id)sender;@end
?
CLLocationManagerDelegate是定位服務的委托,常用的位置變化回調方法是:
locationManager:didUpdateToLocation:fromLocation: locationManager:didFailWithError:
CLLocationManager 是定位服務管理類,通過它可以設置定位服務的參數、獲取經緯度等。
m中加載方法
- (IBAction)findMe:(
id)sender {self.locationManager =
[[[CLLocationManager alloc] init] autorelease];self.locationManager.delegate =
self;self.locationManager.desiredAccuracy =
kCLLocationAccuracyBest;self.locationManager.distanceFilter =
1000.0f;[self.locationManager startUpdatingLocation];[activity startAnimating];NSLog(@"start gps");
}
CLLocationManager 是的startUpdatingLocation方法啟動所有定位硬件,對應的方法是stopUpdatingLocation,通過調用該方法關閉定位服務器更新,為了省電必須在不用的時候調用該方法關閉定位服務。
此外,我們還可以在這里設定定位服務的參數,包括:distanceFilter和desiredAccuracy。
distanceFilter,這個屬性用來控制定位服務更新頻率。單位是“米”。 desiredAccuracy,這個屬性用來控制定位精度,精度
越高耗電量越大。
定位精度?
desiredAccuracy精度參數可以iOS SDK通過常量實現:
? kCLLocationAccuracyNearestTenMeters,10米?
? kCLLocationAccuracyHundredMeters ,100米
? kCLLocationAccuracyKilometer ,1000米
? kCLLocationAccuracyThreeKilometers,3000米
? kCLLocationAccuracyBest ,最好的精度
? kCLLocationAccuracyBestForNavigation,導航情況下最好精度,iOS 4 SDK新增加。一般要有外接電源時候才能使用。
委托方法用于實現位置的更新
-(
void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *
)oldLocation {latituduText.text = [NSString stringWithFormat:
@"%3.5f",newLocation.coordinate.latitude];longitudeText.text = [NSString stringWithFormat:
@"%3.5f",newLocation.coordinate.longitude];[activity stopAnimating];[locationManager stopUpdatingLocation];NSLog(@"location ok");
}
?
該委托方法不僅可以獲得當前位置(newLocation),還可以獲得上次的位置(oldLocation ),CLLocation 對象coordinate.latitude屬性獲得經度,coordinate.longitude屬性獲得緯度。
[NSString stringWithFormat:@"%3.5f”, newLocation.coordinate.latitude]? 中的%3.5f是輸出整數部分是3位,小數部分是5位的浮點數。
11.2 iOS地圖
iOS應用程序中使用Map Kit API開發地圖應用程序。
其核心是MKMapView類使用。
多數情況下地圖會與定位服務結合使用。
地圖開發一般過程
添加MapKit類庫
MapKit.framework
MapMeViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MapLocation.h"@interface ViewController : UIViewController<CLLocationManagerDelegate, MKReverseGeocoderDelegate, MKMapViewDelegate>
{}@property (retain, nonatomic) IBOutlet MKMapView *
mapView;
@property (retain, nonatomic) IBOutlet UIActivityIndicatorView *
activity;
- (IBAction)findMe:(
id)sender;
@end
?
CLLocationManagerDelegate是定位服務委托。
MKMapViewDelegate是地圖視圖委托,主要方法:
?? -mapView:viewForAnnotation:
?? -mapViewDidFailLoadingMap:withError:
MKReverseGeocoderDelegate是給地理坐標獲得標志點信息的委托,用于地理信息編碼(即:從坐標獲得地點獲得信息),主要委托方法:
?? – reverseGeocoder:didFindPlacemark:
?? – reverseGeocoder:didFailWithError:
m文件中的視圖加載和卸載
- (
void)viewDidLoad {[super viewDidLoad];mapView.mapType =
MKMapTypeStandard;//mapView.mapType = MKMapTypeSatellite;//mapView.mapType = MKMapTypeHybrid;mapView.
delegate =
self;
}
?
mapView.mapType = MKMapTypeStandard;是指定地圖的類型,iOS提供了三種風格的地圖:
? MKMapTypeStandard標準地圖模式
? MKMapTypeSatellite衛星地圖模式
? MKMapTypeHybrid具有街道等信息的衛星地圖模式
mapView.delegate = self;是將委托對象指定為自身。
按鈕事件
- (IBAction)findMe:(
id)sender {CLLocationManager *lm =
[[CLLocationManager alloc] init];lm.delegate =
self;lm.desiredAccuracy =
kCLLocationAccuracyBest;[lm startUpdatingLocation];activity.hidden =
NO;[activity startAnimating];
}
?
點擊按鈕時候通過定位服務獲取當前位置信息。
通過lm.delegate = self;是將委托對象指定為自身。
因此,點擊事件發生時候將會回調CLLocationManagerDelegate委托的
-locationManager:didUpdateToLocation:fromLocation:方法。
回調位置更新方法
#pragma mark CLLocationManagerDelegate Methods
- (
void)locationManager:(CLLocationManager *
)manager didUpdateToLocation:(CLLocation *
)newLocation fromLocation:(CLLocation *
)oldLocation {MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(newLocation.coordinate,
2000,
2000); //[mapView setRegion:viewRegion animated:YES];MKCoordinateRegion adjustedRegion =
[mapView regionThatFits:viewRegion];[mapView setRegion:adjustedRegion animated:YES];manager.delegate =
nil;[manager stopUpdatingLocation];MKReverseGeocoder *geocoder =
[[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];geocoder.delegate =
self;[geocoder start];
}
?
MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000); 該函數能夠創建一個MKCoordinateRegion結構體,第一個參數是一個CLLocationCoordinate2D結構指定了目標區域的中心點,第二個是目標區域南北的跨度單位是米,第三個是目標區域東西的跨度單位是米。后兩個參數的調整會影響地圖縮放。
[[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate]; 創建地理編碼對象geocoder,通過該對象可以把坐標轉換成為地理信息的描述。
geocoder.delegate = self;指定編碼的處理是自身對象。
? [geocoder start];開始編碼處理。
? MKReverseGeocoderDelegate
是地理編碼委托對象,該委托的方法:
? 成功時候調用-reverseGeocoder:didFindPlacemark:
? 失敗時候調用-reverseGeocoder:didFailWithError:
成功編碼回調方法
- (
void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *
)placemark {MapLocation *annotation =
[[MapLocation alloc] init];annotation.streetAddress =
placemark.thoroughfare;annotation.city =
placemark.locality;annotation.state =
placemark.administrativeArea;annotation.zip =
placemark.postalCode;annotation.coordinate =
geocoder.coordinate;[mapView addAnnotation:annotation]; [annotation release]; geocoder.delegate =
nil;[geocoder autorelease];[activity stopAnimating];activity.hidden =
YES;
}
?
成功編碼后需要在該方法中創建標注對象(MapLocation)。MapLocation 是我們自定義的實現MKAnnotation協議標注對象。 該方法的placemark是MKPlacemark獲得很多地理信息,詳細見下表。
[mapView addAnnotation:annotation]; 為地圖添加標注,該方法將會觸發mapView:viewForAnnotation:方法回調。
MKPlacemark類屬性
addressDictionary? 地址信息的dictionary
thoroughfare? 指定街道級別信息
subThoroughfare? 指定街道級別的附加信息
locality? 指定城市信息
subLocality? 指定城市信息附加信息
administrativeArea? 行政區域
subAdministrativeArea? 行政區域附加信息
country? 國家信息
countryCode? 國家代號
postalCode? 郵政編碼
失敗編碼回調方法
- (
void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *
)error {UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:@"地理解碼錯誤息"message:@"地理代碼不能識別" delegate:nilcancelButtonTitle:@"Ok"otherButtonTitles:nil];[alert show];[alert release];geocoder.delegate =
nil;[geocoder autorelease];[activity stopAnimating];
}
?
MKMapViewDelegate
是地圖視圖委托對象,本例子我們使用的方法:
? - mapView:viewForAnnotation:為地圖設置標注時候回調方法。
? -mapViewDidFailLoadingMap:withError:地圖加載錯誤時候回調方法。
地圖標注回調方法
#pragma mark Map View Delegate Methods
- (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(
id <MKAnnotation>
) annotation {MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:
@"PIN_ANNOTATION"];if(annotationView ==
nil) {annotationView =
[[[MKPinAnnotationView alloc] initWithAnnotation:annotationreuseIdentifier:@"PIN_ANNOTATION"] autorelease];}annotationView.canShowCallout =
YES;annotationView.pinColor =
MKPinAnnotationColorRed;annotationView.animatesDrop =
YES;annotationView.highlighted =
YES;annotationView.draggable =
YES;return annotationView;
}
?
與表格視圖單元格處理類似,地圖標注對象由于會很多,因此需要重復利用,通過
dequeueReusableAnnotationViewWithIdentifier方法可以查找可重復利用的標注對象,以達到節省內存的目的。
annotationView.canShowCallout = YES;指定標注上的插圖,點擊圖釘有氣泡顯示。
annotationView.pinColor 設置圖釘的顏色。
annotationView.animatesDrop動畫效果。
地圖加載失敗回調方法
- (
void)mapViewDidFailLoadingMap:(MKMapView *)theMapView withError:(NSError *
)error {UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:@"地圖加載錯誤"message:[error localizedDescription] delegate:nil cancelButtonTitle:@"Ok"otherButtonTitles:nil];[alert show];[alert release];
}
?
自定義地圖標注對象?
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MapLocation : NSObject <MKAnnotation, NSCoding>
{NSString *
streetAddress;NSString *
city;NSString *
state;NSString *
zip;CLLocationCoordinate2D coordinate;
}
@property (nonatomic, copy) NSString *
streetAddress;
@property (nonatomic, copy) NSString *
city;
@property (nonatomic, copy) NSString *
state;
@property (nonatomic, copy) NSString *
zip;
@property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
@end
?
作為地圖標注對象實現MKAnnotation協議是必須的,只有實現該協議才能使該類成為標注類。實現NSCoding協議是可選的,實現該協議可以使標注對象能夠復制。 里面的屬性有哪些要看你自己的需要。
MapLocation.m
- (NSString *
)title {return @"您的位置!";
}
- (NSString *
)subtitle {NSMutableString *ret = [NSMutableString
string];if (streetAddress)[ret appendString:streetAddress]; if (streetAddress && (city || state ||
zip)) [ret appendString:@" ? "];if (city)[ret appendString:city];if (city &&
state)[ret appendString:@", "];if (state)[ret appendString:state];if (zip)[ret appendFormat:@", %@", zip];return ret;
}
?
title 和subtitle 是MKAnnotation協議要求實現的方法。
MapLocation.m
#pragma mark -
- (
void)dealloc {[streetAddress release];[city release];[state release];[zip release];[super dealloc];
}
#pragma mark -
#pragma mark NSCoding Methods
- (
void) encodeWithCoder: (NSCoder *
)encoder {[encoder encodeObject: [self streetAddress] forKey: @"streetAddress"];[encoder encodeObject: [self city] forKey: @"city"];[encoder encodeObject: [self state] forKey: @"state"];[encoder encodeObject: [self zip] forKey: @"zip"];
}
- (
id) initWithCoder: (NSCoder *
)decoder {if (self =
[super init]) {[self setStreetAddress: [decoder decodeObjectForKey: @"streetAddress"]];[self setCity: [decoder decodeObjectForKey: @"city"]];[self setState: [decoder decodeObjectForKey: @"state"]];[self setZip: [decoder decodeObjectForKey: @"zip"]];}return self;
}
?
encodeWithCoder:和initWithCoder:是NSCoding協議要求實現方法。
11.3 Web地圖
在iOS中我們還可以使用Web地圖。
?
?
- (IBAction)webMap:(
id)sender {CLLocation *lastLocation =
[locationManager location];if(!
lastLocation) {UIAlertView *
alert;alert =
[[UIAlertView alloc] initWithTitle:@"系統錯誤" message:@"還沒有接收到數據!" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];[alert show];[alert release];return;}NSString *urlString =
[NSString stringWithFormat:@"http://maps.google.com/maps?q=Here+I+Am!@%f,%f", lastLocation.coordinate.latitude, lastLocation.coordinate.longitude];NSURL *url =
[NSURL URLWithString:urlString];[[UIApplication sharedApplication] openURL:url];
}
與iOS6的蘋果didUpdateLocations代替didUpdateToLocation的釋放。任何人都可以解釋如何didUpdateLocations?
本文地址 :CodeGo.net/507856/?
-------------------------------------------------------------------------------------------------------------------------
1. 我以下的委托,以獲得最后一個位置?
- (void)locationManager:(CLLocationManager *)manager?
?didUpdateToLocation:(CLLocation *)newLocation?
? ?fromLocation:(CLLocation *)oldLocation
上述委托棄用的iOS 6。現在,下面應該
- (void)locationManager:(CLLocationManager *)manager?
? didUpdateLocations:(NSArray *)locations
為了獲得最后的位置,只需獲取數組的最后一個對象:
[locations lastObject]
換句話說,[locations lastObject](新代表)等于newLocation(老代表)。?
2. 它給你的對象數組來訪問最后一個位置你
[locations lastObject]
由此
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
3. 這里沒有其他的答案中解釋了為什么有一個位置陣列,以及如何將新didUpdateLocations:提供的數組。 貶低的目的locationManager:didUpdateToLocation:fromLocation:和發送位置一個NSArray,而不是在后臺運行時降低功耗。 與iPhone 5開始時,GPS芯片具有存儲位置的一段,然后傳送在一次陣列中的他們所有的能力。這被稱為延遲的位置更新。這允許主CPU進入睡眠狀態,而在背景中較長的時間。的iOS不具備啟動主CPU的每個位置更新時,CPU可以睡,而GPS芯片集的位置。 您可以檢查這個deferredLocationUpdatesAvailable方法。如果可用,您可以啟用allowDeferredLocationUpdatesUntilTraveled:timeout:方法。條件適用,看到這個答案的細節。?
4. 如果你支持的iOS 5和6,你應該叫
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations,?
從舊
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation?
功能,通過建立的位置的陣列。
本文標題 :didUpdateLocations代替didUpdateToLocation
本文地址 :CodeGo.net/507856/?
繼續瀏覽 :Maven的javadoc中,插件和故障安全maven的插件缺失時生成JBoss Seam的例子
您可以會感興趣的文章:
1. EmberJS嵌套視圖和控制器
2. listview與復選框,單選按鈕,TextView的和按鈕無法正常工作在Android
3. 使用自定義控制臺為Visual Studio控制臺應用程序調試
4. 升級到4.5的Xcode后的iOS 5 SDK中消失了
5. 從基本形式訪問連接字符串會導致錯誤的設計師
6. 在小區的空值處理
7. 無法顯示在欲望的格式報告[關閉]
8. Mysql的動態觸發創建存儲過程
9. NoClassDefFoundError的:android/support/v4/content/LocalBroadcastManager
10. 如何正確地安裝mysqlconnecter java嗎?
11. 可以選擇的樣式元素,以便選定的選項樣式顯示下拉列表時,'封閉'?
12. 在JavaEE的6子進程執行
13. R和矩陣1的行
14. 旋轉和尺度不變性的模板匹配在OpenCV的[復制]
15. 在列表中創建使用數據填充的等高線圖
16. 安卓+PhoneGap的攔截的URL(相當于iOS的shouldStartLoadWithRequest的)
17. 泛型類與約束訪問問題
18. 什么是法律約束緩存事件意思?
19. SBT:添加依賴scalatest庫。在哪里?
20. 什么是PK和FK我應該分配給我的桌子嗎?
IOS定位核心與地圖
? ? ? ? ? ? ???
Core Location以及Map框架包通常能給我們的應用程序添加定位和地圖相關的服務。Core Location框架包通常是使用硬件設備來進行定位服務的,Map框架包通常能夠使你的應用程序做一些地圖展示與交互的相關功能。地圖的定位服務一般需要依賴設備的硬件組成部分。如果有定位的硬件設備,那么肯定是可以利用地圖框架包來進行地圖的一些相關的操作。?
為了能夠在項目中使用到位置服務以及地圖展示的相關功能,你必須要導入Core Location?和Map這兩個框架包。如果你不知道怎么做,那么請參照如下步驟。?
1.點擊你的項目工程圖標文件。?
2.然后選擇target選項,如圖1所示。?
3.然后選擇Build Phase模塊欄。?
4.然后點開Link Binary With Libraries欄目,在點擊+號按鈕。
圖1?添加相關的框架包
5.添加MapKit.framework和CoreLocation.framework這兩個庫
6.在使用地圖和定位的地方,導入:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
MKMapView是UIView的子類,所以可以像一個普通的View一樣添加到ViewController的View當中。
?
以下是相關的代碼
ViewController.h
#import?<UIKit/UIKit.h>? #import?<CoreLocation/CoreLocation.h>? #import?<MapKit/MapKit.h>? #import?"MyAnnotation.h"? @interface?ViewController : UIViewController <MKMapViewDelegate,CLLocationManagerDelegate>? // MapView @property (nonatomic,strong) MKMapView *myMapView;// 地圖控件? // LocationManager @property (nonatomic,strong) CLLocationManager *myLocationManager;// 位置管理器? @property (nonatomic,strong) CLGeocoder *myGeoCoder ;// 地理位置和真實地址轉換? @end?
?
ViewController.m
#import?"ViewController.h"? #import?"MKMapView+ZoomLevel.h"? @interface?ViewController ()? @end? @implementation ViewController? @synthesize myMapView;? @synthesize myLocationManager;? @synthesize myGeoCoder;? - (void)viewDidLoad? {? ????[super?viewDidLoad];? ???// Do any additional setup after loading the view, typically from a nib. ????// 設置根View的背景顏色 ????self.view.backgroundColor = [UIColor colorWithRed:0x33 / 255.0f green:0x66 / 255.0f blue:0x99 / 255.0f alpha:0xFF / 255.0f];? ????// 初始化MapView并且設置MapView顯示的邊界 ????self.myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];? // self.myMapView.mapType = MKMapTypeSatellite; // self.myMapView.mapType = MKMapTypeHybrid; ????self.myMapView.mapType = MKMapTypeStandard;? ????self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;? ????self.myMapView.delegate?= self;? ? ????CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(40.034122, 116.289574);? ????MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinate:coordinate title:@"我的位置" subTitle:@"這里就是寡人的位置,嘿嘿!"];? ????annotation.pinColor = MKPinAnnotationColorPurple;? ? ????[self.myMapView addAnnotation:annotation];? ? ????[self.myMapView setShowsUserLocation:YES];? ????[self.myMapView setCenterCoordinate:coordinate zoomLevel:15 animated:YES];? ? ????[self.view addSubview:myMapView];? ? ????if([CLLocationManager locationServicesEnabled]){? ????????self.myLocationManager = [[CLLocationManager alloc]init];? ????????self.myLocationManager.delegate?= self;? // // 提示用戶是否允許當前應用使用地理位置,已過時,在Info.plist中使用NSLocationUsageDescription鍵值替換 // self.myLocationManager.purpose = @"提示用戶是否允許當前應用使用位置,已過時"; ????????[self.myLocationManager startUpdatingLocation];? ????}else{? ????????NSLog(@">>>>>>>>>> 位置服務不可用 <<<<<<<<<<<<");? ????????UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的位置服務當前不可用,請打開位置服務后重試"?delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];? ????????[alertView show];? ????}? ? ????CLLocation *location = [[CLLocation alloc]initWithLatitude:40.034122 longitude:116.289574];? ? ????self.myGeoCoder = [[CLGeocoder alloc]init];? ????[self.myGeoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks,NSError *error){? ????????if(error == nil && [placemarks count] > 0){? ????????????CLPlacemark *pm = [placemarks objectAtIndex:0];? ????????????NSLog(@"國家:%@" ,pm.country);? ????????????NSLog(@"郵編:%@",pm.postalCode);? ????????????NSLog(@"Locality:%@",pm.locality);? ????????}else?if(error == nil && [placemarks count] == 0){? ????????????NSLog(@"沒有地址返回");? ????????}else?if(error != nil){? ????????????NSLog(@"出錯了:%@",error);? ????????}? ????}];? ? ????[self.myGeoCoder geocodeAddressString:@"中國北京市海淀區花園東路10號高德大廈" completionHandler:^(NSArray *placemarks,NSError *error){? ????????if(nil == error && [placemarks count] > 0){? ????????????NSLog(@"placemarks count:%i",[placemarks count]);? ????????????CLPlacemark *pm = [placemarks objectAtIndex:0];? ????????????NSLog(@"longitude=%f",pm.location.coordinate.longitude);? ????????????NSLog(@"latitude=%f",pm.location.coordinate.latitude);? ????????}else?if([placemarks count] == 0 && error == nil){? ????????????NSLog(@"找不到給定地址的經緯度");? ????????}else?if(nil != nil){? ????????????NSLog(@"發生了錯誤:%@",error);? ????????}? ????}];? ? ? }? - (void)didReceiveMemoryWarning? {? ????[super?didReceiveMemoryWarning];? ????// Dispose of any resources that can be recreated. ? }? -(void)viewDidUnload? {? ????[super?viewDidUnload];? ????self.myMapView = nil;? ????[self.myLocationManager stopUpdatingLocation];? ????self.myLocationManager = nil;? }? -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation? {? ????return?YES;? }? ? /*******************************************************************************************/ /*******************************************************************************************/ /*************************** MapView的Delegate的方法,全部都是Option的 *************************/ /*******************************************************************************************/ /*******************************************************************************************/ /*******************************************************************************************/ - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {? ????NSLog(@"mapView:regionWillChangeAnimated:方法被調用");? }? // 用戶的地理位置發生改變的時候調用 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {? ????NSLog(@"mapView:regionDidChangeAnimated:方法被調用");? }? // 當地圖界面將要加載的時候將會調用這個方法 - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView{? ????NSLog(@"mapViewWillStartLoadingMap:方法被調用");? }? // 當地圖界面加載完成的時候將要調用這個方法 - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView{? ????NSLog(@"mapViewDidFinishLoadingMap:方法被調用");? }? // 當地圖界面加載失敗的時候調用這個方法 - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error{? ????NSLog(@"mapViewDidFailLoadingMap:withError:方法被調用,error is:%@" , [error description]);? }? // 添加到地圖的Annotation // mapView:viewForAnnotation: provides the view for each annotation. // This method may be called for all or some of the added annotations. // For MapKit provided annotations (eg. MKUserLocation) return nil to use the MapKit provided annotation view. - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation? {? ????MKAnnotationView *view = nil;? ????if([annotation isKindOfClass:[MyAnnotation?class]] == NO){? ????????return?view;? ????}? ????if([mapView isEqual:self.myMapView] == NO){? ????????return?view;? ????}? ? ????MyAnnotation *senderAnnotation = (MyAnnotation*)annotation;? ????NSString *pinReusableIdentifier = [MyAnnotation reusableIdentifierForPinColor:senderAnnotation.pinColor];? ????MKPinAnnotationView *annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];? ????if(annotationView == nil){? ????????annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:senderAnnotation reuseIdentifier:pinReusableIdentifier];? ????????[annotationView setCanShowCallout:YES];? ????}? ????annotationView.pinColor = senderAnnotation.pinColor;? ? ????NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);? ????NSString *documentPath = [paths objectAtIndex:0];? ? ????NSString *cachePath = [documentPath stringByAppendingString:@"/images"];? ????NSString *cacheFile = [cachePath stringByAppendingString:@"icon.image"];? ????if([[NSFileManager defaultManager]fileExistsAtPath:cacheFile]){? ????????UIImage *image = [UIImage imageWithContentsOfFile:cacheFile];? ????????if(image != nil){? ????????????annotationView.image = image;? ????????????NSLog(@"通過本地設置圖片");? ????????}else{? ????????????[self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];? ????????}? ????}else{? ????????[self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];? ????}? ????view = annotationView;? ? ????return?view;? }? -(void) setAnnotionImageByUrl:(MKPinAnnotationView *)annotationView cacheFile:(NSString *) cacheFile{? ????NSLog(@"通過網絡設置文件");? ????dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);? ????dispatch_async(queue, ^{? ? ? ????????NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/img/duanwulogo_94a0060bda0885d1c2320ca0d7d7c342.gif"];? ????????NSData *data = [NSData dataWithContentsOfURL:url];? ????????if(data != nil){? ????????????[data writeToFile:cacheFile atomically:YES];? ????????????UIImage *image = [UIImage imageWithData:data];? ????????????dispatch_queue_t mainQueue = dispatch_get_main_queue();? ????????????dispatch_async(mainQueue, ^{? ????????????????if(image != nil){? ????????????????????annotationView.image = image;? ????????????????}? ????????????});? ????????}? ????});? }? /**? // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map.? // The delegate can implement this method to animate the adding of the annotations views.? // Use the current positions of the annotation views as the destinations of the animation.? - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;? ? // mapView:annotationView:calloutAccessoryControlTapped: is called when the user taps on left & right callout accessory UIControls.? - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;? - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);? - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);? ? - (void)mapViewWillStartLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);? - (void)mapViewDidStopLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);? - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation NS_AVAILABLE(NA, 4_0);? - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error NS_AVAILABLE(NA, 4_0);? - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState? fromOldState:(MKAnnotationViewDragState)oldState NS_AVAILABLE(NA, 4_0);? ? - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(NA, 4_0);? ? // Called after the provided overlay views have been added and positioned in the map.? - (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews NS_AVAILABLE(NA, 4_0);? - (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated NS_AVAILABLE(NA, 5_0);? */ ? ? /*******************************************************************************************/ /*******************************************************************************************/ /*************************** 位置相關 *************************/ /*******************************************************************************************/ /*******************************************************************************************/ /*******************************************************************************************/ ? -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation? {? ????NSLog(@"Latitude=%f",newLocation.coordinate.latitude);? ????NSLog(@"Longitude=%f",newLocation.coordinate.longitude);? }? -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error? {? ? ????NSLog(@"獲得位置失敗");? }? @end?
MKMapView+ZoomLevel.h
#import?<MapKit/MapKit.h>? ? @interface?MKMapView (ZoomLevel)? - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate? ??????????????????zoomLevel:(NSUInteger)zoomLevel? ???????????????????animated:(BOOL)animated;? @end?
?
MKMapView+ZoomLevel.m
#import?"MKMapView+ZoomLevel.h"? ? @implementation MKMapView (ZoomLevel)? #define MERCATOR_OFFSET 268435456? #define MERCATOR_RADIUS 85445659.44705395? ? #pragma mark -? #pragma mark Map conversion methods? - (double)longitudeToPixelSpaceX:(double)longitude? {? ????return?round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);? }? ? - (double)latitudeToPixelSpaceY:(double)latitude? {? ????return?round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);? }? - (double)pixelSpaceXToLongitude:(double)pixelX? {? ????return?((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;? }? ? - (double)pixelSpaceYToLatitude:(double)pixelY? {? ????return?(M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;? }? #pragma mark -? #pragma mark Helper methods? ? - (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView? ?????????????????????????????centerCoordinate:(CLLocationCoordinate2D)centerCoordinate? ?????????????????????????????????andZoomLevel:(NSUInteger)zoomLevel? {? ????// convert center coordiate to pixel space ????double?centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];? ????double?centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];? ? ????// determine the scale value from the zoom level ????NSInteger zoomExponent = 20 - zoomLevel;? ????double?zoomScale = pow(2, zoomExponent);? ? ????// scale the map's size in pixel space ????CGSize mapSizeInPixels = mapView.bounds.size;? ????double?scaledMapWidth = mapSizeInPixels.width * zoomScale;? ????double?scaledMapHeight = mapSizeInPixels.height * zoomScale;? ????// figure out the position of the top-left pixel ????double?topLeftPixelX = centerPixelX - (scaledMapWidth / 2);? ????double?topLeftPixelY = centerPixelY - (scaledMapHeight / 2);? ????// find delta between left and right longitudes ????CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];? ????CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];? ????CLLocationDegrees longitudeDelta = maxLng - minLng;? ? ????// find delta between top and bottom latitudes ????CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];? ????CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];? ????CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);? ????// create and return the lat/lng span ????MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);? ????return?span;? }? ? #pragma mark -? #pragma mark Public methods? - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate? ??????????????????zoomLevel:(NSUInteger)zoomLevel? ???????????????????animated:(BOOL)animated? {? ????// clamp large numbers to 28 ????zoomLevel = MIN(zoomLevel, 28);? ? ????// use the zoom level to compute the region ????MKCoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];? ????MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);? ? ????// set the region like normal ????[self setRegion:region animated:animated];? }? ? @end?
MyAnnotation.h
#import?<Foundation/Foundation.h>? #import?<CoreLocation/CoreLocation.h>? #import?<MapKit/MapKit.h>? ? #define REUSABLE_PIN_RED @"Red"? #define REUSABLE_PIN_GREEN @"Green"? #define REUSABLE_PIN_PURPLE @"Purple"? ? @interface?MyAnnotation : NSObject <MKAnnotation>? ? @property (nonatomic,readonly) CLLocationCoordinate2D coordinate;? @property (nonatomic, readonly, copy) NSString *title;? @property (nonatomic, readonly, copy) NSString *subtitle;? ? @property (nonatomic,unsafe_unretained) MKPinAnnotationColor pinColor;? ? -(id) initWithCoordinate:(CLLocationCoordinate2D) coordinate? ???????????????????title:(NSString*) paramTitle? ????????????????subTitle:(NSString*) paramSubTitle;? // 得到顏色 +(NSString *) reusableIdentifierForPinColor:(MKPinAnnotationColor) paramColor;? ? @end?
?
MyAnnotation.m
#import?"MyAnnotation.h"? ? @implementation MyAnnotation? ? @synthesize coordinate,title,subtitle,pinColor;? ? -(id) initWithCoordinate? :(CLLocationCoordinate2D) paramCoordinate title:(NSString *)paramTitle subTitle:(NSString *)paramSubTitle? {? ????self = [super?init];? ????if(self != nil){? ????????coordinate = paramCoordinate;? ????????title = paramTitle;? ????????subtitle = paramSubTitle;? ????????pinColor = MKPinAnnotationColorGreen;? ????}? ????return?self;? }? ? +(NSString *)reusableIdentifierForPinColor:(MKPinAnnotationColor)paramColor? {? ????NSString *result = nil;? ????switch?(paramColor) {? ????????case?MKPinAnnotationColorRed:? ????????????result = REUSABLE_PIN_RED;? ????????????break;? ????????case?MKPinAnnotationColorGreen:? ????????????result = REUSABLE_PIN_GREEN;? ????????????break;? ????????case?MKPinAnnotationColorPurple:? ????????????result = REUSABLE_PIN_PURPLE;? ????}? ????return?result;? }? ? @end?
?
注意,在使用用戶的位置的時候,系統會彈出是否允許應用使用位置的對話框,這個對話框中的提示文字,可以自己進行定義
?
在系統版本是6.0(包括6.0)以上的時候,在Info.plist文件中進行定義
<key>NSLocationUsageDescription</key>
<string>是否可以使用位置?如果需要使用本應用,是必須的!</string>
?
在6.0以下,這樣進行定義
// // 提示用戶是否允許當前應用使用地理位置,已過時,在Info.plist中使用NSLocationUsageDescription鍵值替換// self.myLocationManager.purpose = @"提示用戶是否允許當前應用使用位置,已過時";
總結
以上是生活随笔為你收集整理的iOS 定位和地图的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。