您的位置:首页 > 移动开发

iOS 地图 MKWebView(在中国是使用高德地图)

2016-07-01 01:40 453 查看
一、定位服务介绍

iOS中有三个定位服务组件:

(1)Wifi定位,通过查询一个Wifi路由器的地理位置的信息。比较省电,iPod touch和iPad也可以采用。

(2)蜂窝基站定位,通过移动运用商基站定位。也适合有3G版本的iPod touch和iPad

(3)GPS卫星定位,通过3-4颗GPS定位位置定位,最为准确,但是耗电量大,不能遮挡。

二、项目引用库介绍

(1)CoreLocation.framework 是开发定位服务应用程序的框架

(2)MapKit.framework 是开发地图应用的框架



三、位置模拟

模拟器定位有6个选项:



(1)None

(2)Custom Location

(3)Apple

(4)City Bicycle Ride

(5)City Run

(6)Freeway Drive

单机"Custom Location"选项,会弹出如下对话框,要求设置待模拟的经纬度



设置后,会触发 “-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations;” 函数,打印如下:



locations = (

    "<+26.06400300, +119.3107300> +/- 5.00m (speed -1.00 mps / course -1.00) @ 7/1/16, 4:05:32 PM China Standard Time"

)

注意:如果设置的不是 “Custom Location”,其他的选项我试了一遍,都会报错

触发 “-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error” 函数,打印如下



didFailWithError,error = Error Domain = kCLErrorDomainCode = 0 "(null)"

四、项目实战

(1)ViewController.h

//
//  ViewController.h
//  MapDemo
//
//  Created by 555chy on 6/30/16.
//  Copyright © 2016 555chy. All rights reserved.
//

#import <UIKit/UIKit.h>
//CoreLocation.framework
#import <CoreLocation/CoreLocation.h>
//MapKit.framework
#import <MapKit/MapKit.h>
//标注@protocol<MKAnnotation>
#import "CustomAnnotation.h"

@interface ViewController : UIViewController<CLLocationManagerDelegate, MKMapViewDelegate>

@end


(2)ViewController.m

//
//  ViewController.m
//  MapDemo
//
//  Created by 555chy on 6/30/16.
//  Copyright © 2016 555chy. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property MKMapView *mapView;
@property CLLocationManager *locationManager;
@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

[self initLocationManager];

[self initMapView];

}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

#pragma mark - CLLocationManagerDelegate 获取当前位置
-(void)initLocationManager {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
/*
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
extern const CLLocationAccuracy kCLLocationAccuracyBest;
extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;
extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;
extern const CLLocationAccuracy kCLLocationAccuracyKilometer;
extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;

desired  渴望的、想得到的
accuracy 精确性、准确性
*/
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
/*
*  distanceFilter
*  Discussion: 讨论、谈论、详述、论述
*      Specifies the minimum update distance in meters. Client will not be notified of movements of less
*      than the stated value, unless the accuracy has improved. Pass in kCLDistanceFilterNone to be
*      notified of all movements. By default, kCLDistanceFilterNone is used.
*/
//locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.distanceFilter = 1000.0f;
}

/*
This method is deprecated. If locationManager:didUpdateLocations: is implemented, this method will not be called.
当位置变化超过distanceFilter时,会调用该方法(该方法已被废弃,将不会触发该方法)
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(@"didUpdateToLocation, newLocation = %@, oldLocation = %@", newLocation, oldLocation);
}

/*
chronological 按时间的前后循序排列的、编年的
locations is an array of CLLocation objects in chronological order.
当位置变化超过distanceFilter时,会调用该方法
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
NSLog(@"didUpdateLocations, locations = %@", locations);
}

//如果地图查询错误,则会调用下面的协议函数
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"didFailWithError, error = %@", error);
}

/*
没有该函数时,运行MKMapView报错
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
除了实现该函数,还要在Info.plist中添加
NSLocationAlwaysUsageDescription       String  任意的描述语
NSLocationWhenInUseUsageDescription    String  任意的描述语
Discussion: Invoked when the authorization status changes for this application.
*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
/*
typedef NS_ENUM(int, CLAuthorizationStatus) {
// User has not yet made a choice with regards to this application
kCLAuthorizationStatusNotDetermined = 0,

// This application is not authorized to use location services.  Due
// to active restrictions on location services, the user cannot change
// this status, and may not have personally denied authorization
kCLAuthorizationStatusRestricted,

// User has explicitly denied authorization for this application, or
// location services are disabled in Settings.
kCLAuthorizationStatusDenied,

// User has granted authorization to use their location at any time,
// including monitoring for regions, visits, or significant location changes.
kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(NA, 8_0),

// User has granted authorization to use their location only when your app
// is visible to them (it will be made visible to them if you continue to
// receive location updates while in the background).  Authorization to use
// launch APIs has not been granted.
kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0),

// This value is deprecated, but was equivalent to the new -Always value.
kCLAuthorizationStatusAuthorized NS_ENUM_DEPRECATED(10_6, NA, 2_0, 8_0, "Use kCLAuthorizationStatusAuthorizedAlways") __WATCHOS_PROHIBITED = kCLAuthorizationStatusAuthorizedAlways
};
*/
switch (status) {
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusAuthorizedAlways");
[self.locationManager startUpdatingLocation];
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusAuthorizedWhenInUse");
[self.locationManager startUpdatingLocation];
break;
case kCLAuthorizationStatusDenied:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusDenied");
break;
case kCLAuthorizationStatusNotDetermined:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusNotDetermined");
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
//应用在前台的时候可以搜到更新的位置信息
[self.locationManager requestWhenInUseAuthorization];
//应用在前台和后台(suspend或terminated)都可以获取到更新的位置数据信息
//[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
}
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusRestricted");
break;
default:
break;
}
}

#pragma mark - initMapView 初始化地图控件
-(void)initMapView {
self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
self.mapView.zoomEnabled = true;
self.mapView.scrollEnabled = true;
self.mapView.showsBuildings = true;
//显示罗盘
self.mapView.showsCompass = true;
self.mapView.showsScale = true;
self.mapView.showsTraffic = true;
self.mapView.showsUserLocation = true;
[self.mapView setDelegate:self];

[self.view addSubview:self.mapView];

/*
2d坐标
我这里用的是 中国福建省福州市工人文化宫的坐标
北纬N26.03‘39“ 东经E119.17‘57“
*/
CLLocationCoordinate2D coordinate;
//纬度
coordinate.latitude = 26.064003;
//经度
coordinate.longitude = 119.310730;

//设置地图显示范围
MKCoordinateSpan coordinateSpan;
//(0, 180]
coordinateSpan.latitudeDelta = 0.01;
//(0, 360]
coordinateSpan.longitudeDelta = 0.01;

//设置地图中心
MKCoordinateRegion coordinateRegion;
coordinateRegion.center = coordinate;
coordinateRegion.span = coordinateSpan;
//MKCoordinateRegionMake(<#CLLocationCoordinate2D centerCoordinate#>, <#MKCoordinateSpan span#>)

/*
hybrid     杂种的、混合的
satellite  卫星
flyover    立交桥、高架公路

typedef NS_ENUM(NSUInteger, MKMapType) {
MKMapTypeStandard = 0,
MKMapTypeSatellite,
MKMapTypeHybrid,
MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
} NS_ENUM_AVAILABLE(10_9, 3_0) __WATCHOS_PROHIBITED;
*/
[self.mapView setMapType:MKMapTypeStandard];
[self.mapView setRegion:coordinateRegion animated:YES];

//在中心点创建标记
[self createAnnotationWithCoordinate:coordinate];

//获取地图中心的地理位置描述
[self initGeocoderWithCoordinate:coordinate];
}

#pragma mark - MKAnnotation 在相应的坐标点创建标记
-(void)createAnnotationWithCoordinate:(CLLocationCoordinate2D) coordinate {
CustomAnnotation *annotation = [[CustomAnnotation alloc] initWithCoordinate:coordinate];
[self.mapView addAnnotation:annotation];
}

#pragma mark - CLGeocoder 将经纬坐标编码对象转化为地理信息的描述对象
-(void)initGeocoderWithCoordinate:(CLLocationCoordinate2D) coordinate {

//MKReverseGeocoder is now deprecated. Use CLGeocoder in CoreLocation instead.
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//[NSDate date] 是获取当前时间
CLLocation *location = [[CLLocation alloc] initWithCoordinate:coordinate altitude:kCLDistanceFilterNone horizontalAccuracy:kCLLocationAccuracyBest verticalAccuracy:kCLLocationAccuracyBest timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
//NSLog(@"reverseGeocodeLocation completionHandler, placemarks = %@, error = %@ ", placemarks, error);
if(error == nil && placemarks.count > 0) {
for(int i=0;i<placemarks.count;i++) {
CLPlacemark *placemark = [placemarks objectAtIndex:i];
/*
*  addressDictionary
*
*  Discussion:
*    This dictionary can be formatted as an address using ABCreateStringWithAddressDictionary,
*    defined in the AddressBookUI framework.

@property (nonatomic, readonly, copy, nullable) NSDictionary *addressDictionary;

// address dictionary properties
@property (nonatomic, readonly, copy, nullable) NSString *name; // eg. Apple Inc.
@property (nonatomic, readonly, copy, nullable) NSString *thoroughfare; // street name, eg. Infinite Loop
@property (nonatomic, readonly, copy, nullable) NSString *subThoroughfare; // eg. 1
@property (nonatomic, readonly, copy, nullable) NSString *locality; // city, eg. Cupertino
@property (nonatomic, readonly, copy, nullable) NSString *subLocality; // neighborhood, common name, eg. Mission District
@property (nonatomic, readonly, copy, nullable) NSString *administrativeArea; // state, eg. CA
@property (nonatomic, readonly, copy, nullable) NSString *subAdministrativeArea; // county, eg. Santa Clara
@property (nonatomic, readonly, copy, nullable) NSString *postalCode; // zip code, eg. 95014
@property (nonatomic, readonly, copy, nullable) NSString *ISOcountryCode; // eg. US
@property (nonatomic, readonly, copy, nullable) NSString *country; // eg. United States
@property (nonatomic, readonly, copy, nullable) NSString *inlandWater; // eg. Lake Tahoe
@property (nonatomic, readonly, copy, nullable) NSString *ocean; // eg. Pacific Ocean
@property (nonatomic, readonly, copy, nullable) NSArray<NSString *> *areasOfInterest; // eg. Golden Gate Park
thorough 彻底的、全面的、充分的、详尽的
thorough 通行、大道、大街
*/
NSLog(@"reverseGeocodeLocation placemark, locality = %@,%@, thoroughfare = %@,%@, name = %@", placemark.locality, placemark.subLocality, placemark.thoroughfare, placemark.subThoroughfare, placemark.name);
}
}
}];
}

@end


(3)CustomAnnotation.h

//
//  CustomAnnotation.h
//  MapDemo
//
//  Created by 555chy on 7/1/16.
//  Copyright © 2016 555chy. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

//大头针标注
@interface CustomAnnotation : NSObject<MKAnnotation>

@property CLLocationCoordinate2D coordinate;
@property NSString *title;
@property NSString *subtitle;

-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;

@end


(4)CustomAnnotation.m

//
//  CustomAnnotation.m
//  MapDemo
//
//  Created by 555chy on 7/1/16.
//  Copyright © 2016 555chy. All rights reserved.
//

#import "CustomAnnotation.h"

@implementation CustomAnnotation

-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
if(self = [super init]) {
self.coordinate = coordinate;
self.title = @"标题";
self.subtitle = @"子标题";
}
return self;
}

@end


五、运行截图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: