iOS_mapKit與Core Location

目  錄:
1、使用MKMap控件
2、根據地址定位
3、在地圖上添加錨點
 
  iOS從3.0版本開始提供了MapKit.frameword支持。該框架提供了一個可被嵌入到應用程序中的地圖視圖類MKMapView,該地圖視圖類包含一個可上下、左右滾動的地圖視圖,並且能夠很是方便地在地圖中添加定製消息,並能夠將其嵌入到應用程序中,經過編程的方式設置地圖的各類屬性(包含當前地圖顯示的區域以及用戶當前所在位置)。
  iOS從4.0開始,MapKit框架支持可拖動標註和定製覆蓋層。可拖動標註容許開發者以編程的方式或用戶交互方式來重定位某個標註的位置;覆蓋層則可用於建立有多個點組成的複雜標註,這種覆蓋層可用於建立公交路線、公園邊界或氣象信息(如雷達數據)等。
   如今不少的社交軟件都引入了地圖和定位功能,要想實現這2大功能,那就不得不學習其中的2個框架:MaKit和CoreLocation
  (1)CoreLocation框架可使用硬件設備來進行定位服務
  (2)MapKit框架可以使應用程序作一些地圖展現與交互的相關功能 
  iOS定位支持的3中模式:手機基站、WIFI、GPS
1、使用MKMapView控件
  MKMapView控件中位於MapKit.framework中,所以爲了在iOS應用中使用該控件,須要完成兩件事情:1,爲該應用添加MapKit框架;2,在使用MKMapView及相關類的源文件中使用「#import<MapKit/MapKit.h>」導入MapKit.framework的頭文件。本章絕大部分示例都使用了MKMapView,所以都須要執行上面兩步操做。
  1.指定地圖顯示中心和顯示區域
  爲了控制地圖顯示指定區域,只要兩步便可。
  一、建立一個MKCoordinateRegion結構體變量,該結構體變量包含center,span兩個成員,其中center控制顯示區域的中心,span控制顯示區域的範圍。
  二、將MKMapView的region屬性設爲制定的MKCoordinateRegion結構體變量。
  iOS中爲開發者提供瞭如下三種地圖類型,開發者能夠經過設置MKMapView的mapViewType設置地圖類型。
  (1)MKMapTypeStandard 普通地圖
  (2)MKMapTypeSatellite 衛星雲圖 
  (3)MKMapTypeHybrid 普通地圖覆蓋於衛星雲圖之上
   2.在地圖中使用大頭針
  (1)經過MapView的addAnnotation方法能夠添加一個大頭針到地圖上
  (2)經過MapView的addAnnotations方法能夠添加多個大頭針到地圖上
    - (void)addAnnotation:(id <MKAnnotation>)annotation;
    說明:須要傳入一個遵照了MKAnnotation協議的對象(下面代碼中進行演示)
  不但如此還要實現MapView的代理方法
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    static NSString *ID = @"anno";
    MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
    if (annoView == nil) {
        annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];
        // 顯示氣泡
        annoView.canShowCallout = YES;
        // 設置綠色
        annoView.pinColor = MKPinAnnotationColorGreen;
    }
    
    return annoView;
}
  案例:顯示指定區域的地圖
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "MyAnnotation.h"
@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;

@property (weak, nonatomic) IBOutlet UITextField *latitude;
@property (weak, nonatomic) IBOutlet UITextField *longitude;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //設置地圖的顯示風格
    self.mapView.mapType = MKMapTypeStandard;
    //設置地圖可縮放
    self.mapView.zoomEnabled = YES;
    //設置地圖可滾動
    self.mapView.scrollEnabled = YES;
    //設置地圖可旋轉
    self.mapView.rotateEnabled = YES;
    //設置顯示用戶顯示位置
    self.mapView.showsUserLocation = YES;
    //爲MKMapView設置delegate
    self.mapView.delegate = self;
//    [self locateToLatitude:23.12672 longtitude:113.395];
    NSLog(@"用戶當前是否位於地圖中:%d",self.mapView.userLocationVisible);
    
}
- (IBAction)goClicked:(UIButton *)sender
{
    //關閉兩個文本框的虛擬鍵盤
//    [self.latitude resignFirstResponder];
//    [self.longitude resignFirstResponder];
    //經度
    NSString *latitudeStr = self.latitude.text;
    //緯度
    NSString *longtitudeStr = self.longitude.text;
    //若是用戶輸入的經度、緯度爲空
    if (latitudeStr != nil && latitudeStr.length > 0
        && longtitudeStr!= nil && longtitudeStr.length > 0)
    {
        //設置經度、緯度
        [self locateToLatitude:latitudeStr.floatValue longtitude:longtitudeStr.floatValue];
    }
}
-(void)locateToLatitude:(CGFloat)latitude longtitude:(CGFloat)longitude
{
    //設置地圖中的的經度、緯度
    CLLocationCoordinate2D center = {latitude,longitude};
    //也可使用以下方式設置經度、緯度
    //center.latitude = latitude;
    //center.longitude = longitude;
    //設置地圖顯示的範圍
    MKCoordinateSpan span;
    //地圖顯示範圍越小,細節越清楚;
    span.latitudeDelta = 0.01;
    span.longitudeDelta = 0.01;
    //建立MKCoordinateRegion對象,該對象表明地圖的顯示中心和顯示範圍
    MKCoordinateRegion region = {center,span};
    //設置當前地圖的顯示中心和顯示範圍
    [self.mapView setRegion:region animated:YES];
    
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
    [self.mapView addGestureRecognizer:longPress];
}

-(void)longPress:(UILongPressGestureRecognizer *)sender
{
    CGPoint location = [sender locationInView:self.mapView];
    //轉換經緯度
    CLLocationCoordinate2D coordinate = [self.mapView convertPoint:location toCoordinateFromView:self.mapView];
    // 建立標註
    MyAnnotation *annotation = [[MyAnnotation alloc]init];
    annotation.coordinate = coordinate;
    annotation.title = @"新的標註";
    annotation.subtitle = @"開發...";
    [self.mapView addAnnotation:annotation];
}
#pragma mark - mapView代理方法

#pragma mark 顯示標註視圖
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    static NSString *annotationID = @"annotation";
    MKPinAnnotationView *view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationID];
    if (!view)
    {
        view = [[MKPinAnnotationView alloc]init];
    }
    view.annotation = annotation;
//    view.leftCalloutAccessoryView
    view.pinColor = MKPinAnnotationColorGreen;
    view.canShowCallout = YES;
    return view;
}
#pragma mark 代理方法
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    
    CLLocationCoordinate2D coordinate = userLocation.location.coordinate;
    MKCoordinateSpan span = {0.001,0.001};
    MKCoordinateRegion region = {coordinate,span};
    //設置顯示區域
    [self.mapView setRegion:region animated:YES];
    
    MyAnnotation *annotation = [[MyAnnotation alloc]init];
    annotation.coordinate = coordinate;
    annotation.title = @"中國";
    annotation.subtitle = @"好牛B的地方";
    //讓地圖顯示標註的區域
    [self.mapView setCenterCoordinate:annotation.coordinate animated:YES];
    

}
//當MKMapView顯示區域將要發生改變時激發該方法
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    NSLog(@"地圖控件的顯示區域要發生改變");
}
//當MKMapView顯示區域改變完成時激發該方法
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    NSLog(@"地圖控件完成了改變");
}
//當地圖控件MKMapView開始加載數據時激發該方法
-(void)mapViewWillStartLoadingMap:(MKMapView *)mapView
{
    NSLog(@"地圖控件開始加載地圖數據");
    //建立MKCoordinateRegion對象,該對象表明地圖的顯示中心和顯示範圍
    MKCoordinateRegion region = mapView.region;
    self.latitude.text = [NSString stringWithFormat:@"%f",region.center.latitude];
    self.longitude.text = [NSString stringWithFormat:@"%f",region.center.longitude];
    
}
//當MKMapView加載數據完成時激發該方法
-(void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
    NSLog(@"地圖控件加載地圖數據完成");
    NSLog(@"%@",mapView);
}
//當MKMapView加載數據失敗時激發該方法
-(void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error
{
    NSLog(@"地圖控件加載地圖數據發生錯誤:錯誤信息:%@",error);
}
//當MKMapView開始渲染地圖時激發該方法
-(void)mapViewWillStartRenderingMap:(MKMapView *)mapView
{
    NSLog(@"地圖控件開始渲染地圖");
}
//當MKMapView渲染地圖完成時激發該方法
-(void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered
{
    NSLog(@"地圖控件渲染完成");
}
@end

  MyAnnotation.h文件內容git

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MyAnnotation : NSObject<MKAnnotation>
@property(copy,nonatomic)NSString *title;
@property(copy,nonatomic)NSString *subtitle;
@property(assign,nonatomic)CLLocationCoordinate2D coordinate;
@end

  程序運行結果以下:編程

  程序中還爲MKMapView指定了delegate,所以該delegate將會響應地圖位置改變、加載過程當中的相關事件,因此你們能夠看到Xcode的控制輸出消息。框架

2、根據地址定位工具

  1.地址解析與反向地址解析學習

  地址解析:把普通用戶能看懂的字符串地址轉換爲經度、緯度。atom

  反向地址解析:把經度、緯度轉換成普通的字符串地址。spa

  iOS爲地址解析提供了CLGeocoder工具類,該工具類提供了以下3種方法來進行地址解析和反向地址解析。3d

  -geocodeAddressString:completionHandler: :根據給定的字符串地址進行解析,解析將會獲得該地址對應的經度、緯度信息。代理

  -geocodeAddressString:inRegion:completonHandler: :根據給定的字符串進行解析,解析將會獲得該地址對應的經度、緯度信息。code

  -reverseGeocodeLocation:completionHandler: :根據給定的經度、緯度地址方向解析獲得字符串地址。

  通常來講:地址解析可能獲得多個結果——這是由於全球徹底可能有多個同名的地點;但反向地址解析通常只會獲得一個結果——由於根據指定經度、緯度獲得的地址一般是惟一的。

  2.根據地址定位

  根據地址定位的思路很是簡單,只要以下兩步便可。

  (1)使用CLGeocoder根據字符串地址獲得該地址的經度、緯度。

  (2)根據解析獲得的經度、緯度進行定位。

  

#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface ViewController ()<CLLocationManagerDelegate>
@property(strong,nonatomic)CLLocationManager *locationManager;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 建立定位管理器
    self.locationManager = [[CLLocationManager alloc]init];
    //獲取用戶受權
    [self.locationManager requestAlwaysAuthorization];
    
    //獲取當前受權狀態
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
    if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse)
    {
        NSLog(@"受權經過");
    }
    else
    {
        NSLog(@"受權不經過");
    }
    //設置代理
    self.locationManager.delegate = self;
    //設置經度
    self.locationManager.desiredAccuracy =kCLLocationAccuracyBest;
    //開始定位
    [self.locationManager startUpdatingLocation];
}
#pragma mark - 定位管理器的代理方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
   // NSLog(@"%@",locations);
    //取出位置信息
    CLLocation *location = [locations lastObject];
    
    //建立地理信息編解碼對象
    CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
    
    //轉換位置信息
    [geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
//        NSLog(@"%@",placemarks[0]);
        CLPlacemark *placeMark = placemarks[0];
        NSLog(@"%@%@",placeMark.country,placeMark.locality);
    }];
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"%@",error);
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
    [geoCoder geocodeAddressString:@"西三旗" completionHandler:^(NSArray *placemarks, NSError *error) {
        if ([placemarks count] == 0) {
            NSLog(@"沒有找到相應的地理信息");
        }
        else
        {
            CLPlacemark *placemark = [placemarks objectAtIndex:0];
            //NSLog(@"%@",placeMark);
            // NSLog(@"%f,%f",placeMark.location.coordinate.latitude,placeMark.location.coordinate.longitude);
            
            MKMapItem *mapItem1 = [[MKMapItem alloc]initWithPlacemark:(MKPlacemark*)placemark];
            [geoCoder geocodeAddressString:@"八達嶺長城" completionHandler:^(NSArray *placemarks, NSError *error) {
                MKMapItem *mapItem2 = [[MKMapItem alloc]initWithPlacemark:(MKPlacemark*)placemarks[0]];
                //調用系統地圖打開一個位置
                [MKMapItem openMapsWithItems:@[mapItem1,mapItem2] launchOptions:nil];
            }];
        }
    }];
}
@end

3、在地圖上添加錨點

  1.添加簡單地錨點

  對於iOS的地圖而言,添加錨點只要調用MKMapView的-(void)addAnnotation:(id<MKAnnotation>)annotation方法便可,每調用一次,就像地圖添加一個錨點。MKAnnotation是一個協議,該協議中定義了3個屬性,用於設置和返回錨點的信息。

  - coordinate:用於設置和返回錨點的位置。該屬性值必須是一個CLLocationCoordinate2D結構體變量,封裝了經度、緯度信息。

  - title:用於設置和返回錨點的標題。

  - subtitle:用於設置和返回錨點的副標題。

  2.添加自定義錨點

  錨點由兩部分組成。

  錨點信息:錨點信息包括錨點的位置、標題、副標題等信息,這些信息有MKAnnotation對象表明。

  錨點控件:錨點控件決定地圖上顯示的錨點外觀,包括錨點的圖片等。

  iOS爲錨點控件提供了MKAnnotationView和MKPinAnnotationView,其中MKPinAnnotationView是MKAnnotationView的子類,而MKAnnotationView繼承了UIView——也就是說,它只是一個可視化的UI控件。

  爲定製地圖上的錨點,須要完成以下兩步。

  1.爲MKMapView指定delegate對象。

  2.重寫delegatede-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation方法,該方法的返回值將做爲地圖上的錨點控件。

  案例:在圖上添加錨點

#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "MyAnnoation.h"
@interface ViewController ()<MKMapViewDelegate>
@property(strong,nonatomic)MKMapView *mapView;

@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    // 建立mapView
    self.mapView = [[MKMapView alloc]initWithFrame:self.view.frame];
    //設置地圖的類型
    self.mapView.mapType = MKMapTypeStandard;
    [self.view addSubview:self.mapView];
    
    self.mapView.delegate = self;
    
    //建立標註
    MyAnnoation *annoation = [[MyAnnoation alloc]init];
    annoation.coordinate= CLLocationCoordinate2DMake(40, 100);
    annoation.title = @"中國";
    annoation.subtitle = @"好牛B的地方";
    //添加標註
    [self.mapView addAnnotation:annoation];
    
    //讓地圖顯示標註的區域
    [self.mapView setCenterCoordinate:annoation.coordinate animated:YES];
    
    //添加手勢
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
    [self.mapView addGestureRecognizer:longPress];
}
-(void)longPress:(UILongPressGestureRecognizer *)sender
{

    //獲取當前位置
    CGPoint location = [sender locationInView:self.view];
    //轉換經緯度
    CLLocationCoordinate2D coordinate =[self.mapView convertPoint:location toCoordinateFromView:self.mapView];
    //建立標註
    MyAnnoation *annotation = [[MyAnnoation alloc]init];
    annotation.coordinate = coordinate;
    annotation.title = @"新的標註";
    annotation.subtitle = @"待開發。。";
    //添加標註
    [self.mapView addAnnotation:annotation];
    
}
#pragma mark - mapView代理方法
#pragma mark 顯示標註視圖
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    static NSString *annotationID =@"annotation";
    //先從重用隊列中去找
    MKPinAnnotationView *view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationID];
    //若是找不到,本身建立
    if (!view)
    {
        view = [[MKPinAnnotationView alloc]init];
    }
    //設置屬性
    view.annotation = annotation;
    view.canShowCallout = YES;//顯示氣泡視圖
    view.pinColor = MKPinAnnotationColorPurple;//設置大頭針顏色
    //顯示圖片(這種方式設置圖片會取代大頭針)
    view.image  = [UIImage imageNamed:@"0.png"];
    //設置氣泡的輔助視圖(顯示圖片)
    view.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"0.png"]];
    return view;
}
#pragma mark 選中了標注後的處理

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    NSLog(@"選中了標注");
}
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    NSLog(@"取消了標註");
}
@end
相關文章
相關標籤/搜索