精通iOS开发--第19章 Core Location 和 Map Kit 01 Capabilities 下 示例程序
来源:互联网 发布:数据错误文件被破坏 编辑:程序博客网 时间:2024/05/07 17:30
第19章 Core Location和 Map Kit 01 Capabilities下
CLLocation+Description.h
//
// CLLocation+Description.h
// CLLocationManagerTest
//
// Created by ranzhou on 16/7/8.
// Copyright © 2016年 ranzhouee. All rights reserved.
//
#import <CoreLocation/CoreLocation.h>
@interface CLLocation (Description)
- (void)descripeCLLocation:(CLLocation*)location;
@end
CLLocation+Description.m
//
// CLLocation+Description.m
// CLLocationManagerTest
//
// Created by ranzhou on 16/7/8.
// Copyright © 2016年 ranzhouee. All rights reserved.
//
#import "CLLocation+Description.h"
// Core Location
@implementation CLLocation (Description)
- (void)descripeCLLocation:(CLLocation*)location {
// 地理坐标 // coordinate |kəʊˈɔːdɪnət| noun坐标
CLLocationCoordinate2D coordinate = location.coordinate;
// 纬度 // latitude |ˈlætɪtjuːd| noun纬度
NSLog(@"%f",coordinate.latitude);
// 经度 // longitude |ˈlɒndʒɪtjuːd| noun经度
NSLog(@"%f",coordinate.longitude);
/*
水平精度,horizontalAccuracy描述了以coordinate为圆心的圆的半径,horizontalAccuracy越小精度越高。
若horizontalAccuracy为负值,则表示由于某种原因,而导致无法信任coordinate的值。
horizontal |ˌhɒrɪˈzɒntl| adjective 水平的。
accuracy |ˈækjərəsi| noun Uncountable 精确。
*/
NSLog(@"%f",location.horizontalAccuracy);
// 海拔高度 // altitude |ˈæltɪtjuːd, American -tuːd| noun海拔
NSLog(@"%f",location.altitude);
// 垂直精度,表示海拔高度的精度,如果值为负的,则表示无法获取有效海拔高度。
NSLog(@"%f",location.verticalAccuracy);
// 时间戳,描述的是位置管理器确定位置的时间。
NSLog(@"%@",[location.timestampdateByAddingTimeInterval:[[NSTimeZonelocalTimeZone]secondsFromGMT]]);
}
@end
BIDPlace.h
//
// BIDPlace.h
// CLLocationManagerTest
//
// Created by ranzhou on 16/7/7.
// Copyright © 2016年 ranzhouee. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
// Map Kit annotation |ˌænəˈteɪʃn| noun 注释
@interface BIDPlace :NSObject<MKAnnotation>
@property (copy,nonatomic)NSString *title;
// subtitle |ˈsʌbtaɪtl| noun 副标题
@property (copy,nonatomic)NSString *subtitle;
@property (nonatomic,assign)CLLocationCoordinate2D coordinate;
@property (nonatomic,strong)CLLocation* location;
@end
BIDPlace.m
//
// BIDPlace.m
// CLLocationManagerTest
//
// Created by ranzhou on 16/7/7.
// Copyright © 2016年 ranzhouee. All rights reserved.
//
#import "BIDPlace.h"
@implementation BIDPlace
@end
ViewController.m
//
// ViewController.m
// CLLocationManagerTest
//
// Created by ranzhou on 16/7/7.
// Copyright © 2016年 ranzhouee. All rights reserved.
//
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "BIDPlace.h"
#define TempDescript ([NSString stringWithFormat:@"Class:%@ Cmd:%@ Line:%i",[self class],NSStringFromSelector(_cmd),__LINE__])
@interface ViewController () <CLLocationManagerDelegate,MKMapViewDelegate>
@property (nonatomic,strong)CLLocationManager *locationManager;
@property (nonatomic,strong)MKMapView *mapView;
@property (nonatomic,strong)NSMutableArray<BIDPlace *> *BIDPlaceArry;
@property (nonatomic,assign)double totalDistance;
// -------------------------------------------------------------------
@property (nonatomic,assign)CLLocationCoordinate2D firstUserLocation;
@property (nonatomic,assign)CLLocationCoordinate2D firstLocationResult;
// -------------------------------------------------------------------
@property (nonatomic,strong)NSMutableString *reportStr;
@end
@implementation ViewController
- (void)loadTheMapView
{
self.mapView = [[MKMapViewalloc]initWithFrame:self.view.bounds];
// 自动显示用户的位置,Set to YES to add the user location annotation to the map and start updating its location,因为我们获取到的地理位置与真实位置有偏差,所以通过这个方法来取得正确的促初始位置。
self.mapView.showsUserLocation = YES;
self.mapView.delegate =self;
self.mapView.translatesAutoresizingMaskIntoConstraints = NO;
[self.viewaddSubview:self.mapView];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:self.viewattribute:NSLayoutAttributeLeftrelatedBy:NSLayoutRelationEqualtoItem:self.mapViewattribute:NSLayoutAttributeLeftmultiplier:1.0constant:0.0]];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:self.viewattribute:NSLayoutAttributeRightrelatedBy:NSLayoutRelationEqualtoItem:self.mapViewattribute:NSLayoutAttributeRightmultiplier:1.0constant:0.0]];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:self.viewattribute:NSLayoutAttributeToprelatedBy:NSLayoutRelationEqualtoItem:self.mapViewattribute:NSLayoutAttributeTopmultiplier:1.0constant:0.0]];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:self.viewattribute:NSLayoutAttributeBottomrelatedBy:NSLayoutRelationEqualtoItem:self.mapViewattribute:NSLayoutAttributeBottommultiplier:1.0constant:0.0]];
}
- (void)beginUpdatingLocation
{
if ([CLLocationManagerlocationServicesEnabled])
{
self.locationManager = [[CLLocationManageralloc] init];
/*
在iOS 8.0下要授权,iOS8以后采用了新的授权方式,需要再Info.plist中注册提示的内容。
*/
if ([[[UIDevicecurrentDevice] systemVersion]floatValue] >= 8.0)
{
// NSLocationAlwaysUsageDescription
[self.locationManagerrequestAlwaysAuthorization];
// NSLocationWhenInUseUsageDescription // authorization |ˌɔːθəraɪˈzeɪʃn| noun授权、批准
//[self.locationManager requestWhenInUseAuthorization];
}
}
self.locationManager.delegate = self;
// desiredAccuracy是一个double类型,代表m,kCLLocationAccuracyBest表示提供最好的精度。
// desire |dɪˈzaɪə(r)| noun、v渴望
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// 默认情况下,位置管理器会把检测到的位置更改通知给委托。制定距离筛选器意味着告知位置管理器不要将更改都通知你,仅当位置更改超过特定大小时通知你。设置距离筛选器可以减少应用执行的轮询数量。代表m。
// filter |ˈfɪltə(r)| n 过滤器
self.locationManager.distanceFilter = 20;
// 设置成kCLDistanceFilterNone后将取消前面的distanceFilter相关的设置。恢复到没有筛选器的状态。
// self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeFitness;
self.locationManager.allowsBackgroundLocationUpdates = YES;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
// 启动位置管理器。
[self.locationManagerstartUpdatingLocation];
}
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.reportStr = [[NSMutableStringalloc]init];
[[NSFileManagerdefaultManager]removeItemAtPath:[selfcreateFileName]error:NULL];
self.totalDistance =0;
self.BIDPlaceArry = [[NSMutableArrayalloc]init];
BIDPlace *bid = [[BIDPlacealloc]init];
bid.title =@"起始位置";
bid.subtitle =@"起始位置";
[self.BIDPlaceArryaddObject:bid];
[selfloadTheMapView];
[selfbeginUpdatingLocation];
[selfloadButton];
BOOL bb = [CLLocationManagersignificantLocationChangeMonitoringAvailable];
NSLog(@"%i",bb);
NSLog(@"%i",[UIDevicecurrentDevice].multitaskingSupported);
}
-(void)loadButton {
UIButton *tempButton = [[UIButtonalloc]init];
tempButton.backgroundColor = [[UIColorlightGrayColor]colorWithAlphaComponent:0.5];
[self.viewaddSubview:tempButton];
[tempButton addTarget:selfaction:@selector(showReport)forControlEvents:UIControlEventTouchUpInside];
tempButton.translatesAutoresizingMaskIntoConstraints =NO;
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:tempButtonattribute:NSLayoutAttributeWidthrelatedBy:NSLayoutRelationEqualtoItem:NULLattribute:NSLayoutAttributeNotAnAttributemultiplier:1.0constant:200]];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:tempButtonattribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:NULLattribute:NSLayoutAttributeNotAnAttributemultiplier:1.0constant:40]];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:tempButtonattribute:NSLayoutAttributeCenterXrelatedBy:NSLayoutRelationEqualtoItem:self.viewattribute:NSLayoutAttributeCenterXmultiplier:1.0constant:0]];
[self.viewaddConstraint:[NSLayoutConstraintconstraintWithItem:self.viewattribute:NSLayoutAttributeBottomrelatedBy:NSLayoutRelationEqualtoItem:tempButton attribute:NSLayoutAttributeBottommultiplier:1.0constant:20]];
}
- (void)showReport
{
//NSString *str = [NSString stringWithContentsOfFile:[self createFileName] encoding:NSUTF8StringEncoding error:NULL];
UIAlertController *alertController = [UIAlertControlleralertControllerWithTitle:@"日志"message:self.reportStrpreferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertActionactionWithTitle:@"取消"style:UIAlertActionStyleCancelhandler:nil];
UIAlertAction *okAction = [UIAlertActionactionWithTitle:@"好的"style:UIAlertActionStyleDefaulthandler:nil];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[selfpresentViewController:alertControlleranimated:YEScompletion:nil];
}
/*
1:对于国内地图而言,使用LocationManager定位所获得经纬度,是有一段较大距离的偏移的,国内地图使用的坐标系统是GCJ-02而ios sdk中所用到的是国际标准的坐标系统WGS-84。因为国内使用的是加密后的坐标系GCJ-02就是网络上叫的火星坐标。
2:locationManager就是因为得到的是火星坐标偏移后的经纬度,所以导致在MapView上有很大的偏差,而在MKMapView上通过定位自己位置所获得的经纬度有是准确,因为apple已经对国内地图做了偏移优化。
3:那么临时的解决方法:想要获得自己准确的经纬度可以直接通过MKMapView中对自身定位来获得:
*/
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
staticdispatch_once_t once;
dispatch_once(&once, ^{
dispatch_async(dispatch_get_main_queue(), ^{
self.firstUserLocation = userLocation.coordinate;
// 他告诉地图要显示地图的哪一部分
MKCoordinateRegion coordinateRegion =MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate,1000, 1000);
[self.mapViewsetRegion:coordinateRegionanimated:YES];
self.BIDPlaceArry.firstObject.coordinate = userLocation.location.coordinate;
[self.mapViewaddAnnotation:self.BIDPlaceArry.firstObject];
});
});
}
// 无法确定位置时回调的方法。测试发现经常会出现kCLErrorLocationUnknown错误,随后打开原生地图后再打开就没有问题了。然后过一会又会报kCLErrorLocationUnknown错误。关闭屏幕后重新打开,又会恢复。这应该不是一个错误,因该是苹果为了省电自动做的处理。参考:self.locationManager.activityType = CLActivityTypeFitness;
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
if (error.code ==kCLErrorLocationUnknown)
{
NSLog(@"kCLErrorLocationUnknown");
}
else if(error.code ==kCLErrorDenied)
{
// deny |dɪˈnaɪ| v 否认
NSLog(@"kCLErrorDenied");
}
else
{
NSLog(@"Error.code:%li",error.code);
}
}
// overlay |ˌəʊvəˈleɪ|transitive verb 覆盖 |ˈəʊvəleɪ|noun覆盖物
// polyline ['pɒli:laɪn] n 折线
// render |ˈrendə(r)| v 描述、给某某抹灰
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay
{
if ([overlayisKindOfClass:[MKPolylineclass]])
{
MKPolylineRenderer *renderer=[[MKPolylineRendereralloc]initWithOverlay:overlay];
// stroke |strəʊk|
renderer.strokeColor=[[UIColorredColor]colorWithAlphaComponent:0.5];
renderer.lineWidth=2.0;
return renderer;
}
if([overlayisKindOfClass:[MKCircleclass]])
{
MKCircleRenderer *circle = [[MKCircleRendereralloc]initWithOverlay:overlay];
circle.lineWidth =2.0;
circle.strokeColor = [UIColorblueColor];
circle.fillColor = [[UIColorblueColor]colorWithAlphaComponent:0.5];
return circle;
}
if([overlayisKindOfClass:[MKPolygonclass]])
{
MKPolygonRenderer *polygon = [[MKPolygonRendereralloc]initWithOverlay:overlay];
polygon.lineWidth =2.0;
polygon.strokeColor = [UIColoryellowColor];
polygon.fillColor = [[UIColoryellowColor]colorWithAlphaComponent:0.5];
return polygon;
}
returnnil;
}
/*
manager:第一个参数是该方法的位置管理器。
locations:第二个参数代表的是位置数组,有可能多次位置更新一次性上报,无论何时,数组的最后一项都表示当前位置。
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *lastLocation = locations.lastObject;
// 如果精度太低则放弃次操作。
if (lastLocation.horizontalAccuracy >66.0 || lastLocation.horizontalAccuracy<0)
{
return;
}
// 在下面的代码中记录第一次获取到的经纬度。
staticdispatch_once_t once;
dispatch_once(&once, ^{
self.firstLocationResult = lastLocation.coordinate;
// 记录location是为了计算讲个location之间的距离使用。
self.BIDPlaceArry.firstObject.location = lastLocation;
});
// 如果此时UserLocation还某有更新则return,等待其获取到数据后才继续操作。
if (self.firstUserLocation.longitude==0 || self.firstUserLocation.latitude==0)
{
return;
}
NSMutableArray<CLLocation*> *locationArry = [[NSMutableArrayalloc]init];
[locationArry addObject:[self.BIDPlaceArrylastObject].location];
for(int i=0; i<locations.count; i++)
{
CLLocation *location = [locationsobjectAtIndex:i];
if (location.horizontalAccuracy >70 || location.horizontalAccuracy<0)
{
continue;
}
// 如果新获取到的地理位置只移动了很小的距离,则不记录。
double newDistance = newDistance = [locationArry.lastObjectdistanceFromLocation:location];
if (newDistance <30)
{
continue;
}
[locationArry addObject:location];
}
// 声明一个数组 用来存放画线的点。
CLLocationCoordinate2D coords[locationArry.count];
coords[0] = [selfjustTheCLLocationCoordinate2D:locationArry.firstObject.coordinate];
for (int i=1; i<locationArry.count; i++)
{
CLLocation *tempLocation = [locationArryobjectAtIndex:i];
coords[i] = [selfjustTheCLLocationCoordinate2D:tempLocation.coordinate];
BIDPlace *newBID = [[BIDPlacealloc]init];
newBID.title = [NSStringstringWithFormat:@"%lu",(unsignedlong)self.BIDPlaceArry.count];
newBID.coordinate = coords[i];
newBID.location = tempLocation;
double newDistance = [[locationArryobjectAtIndex:i-1]distanceFromLocation:tempLocation];
self.totalDistance += newDistance;
newBID.subtitle = [NSStringstringWithFormat:@"行程:%f",self.totalDistance];
[self.BIDPlaceArryaddObject:newBID];
// 添加新的标记点。
[self.mapViewaddAnnotation:newBID];
}
// 在不改变缩放级别的情况下,移动到当前位置。
// centerCoordinate allows the coordinate of the region to be changed without changing the zoom level.
[self.mapViewsetCenterCoordinate:coords[locationArry.count-1]animated:YES];
// 在地图上画线
MKPolyline *polyline = [MKPolylinepolylineWithCoordinates:coordscount:locationArry.count];
[self.mapViewaddOverlay:polyline level:MKOverlayLevelAboveLabels];
}
- (CLLocationCoordinate2D)justTheCLLocationCoordinate2D:(CLLocationCoordinate2D)coor
{
CLLocationCoordinate2D coord = coor;
coord.longitude = coord.longitude -( self.firstLocationResult.longitude-self.firstUserLocation.longitude);
coord.latitude = coord.latitude - (self.firstLocationResult.latitude -self.firstUserLocation.latitude);
return coord;
}
- (void)reportRecode:(NSString *)str
{
static NSString *path;
if (path==NULL) {
path = [self createFileName];
}
[[NSString stringWithFormat:@"%@\n",str] writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}
- (NSString*)createFileName
{
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [pathsobjectAtIndex:0];
NSString *filePath = [documentsDirectorystringByAppendingPathComponent:[NSStringstringWithFormat:@"%@.txt",@"调试日志"]];
return filePath;
}
@end
- 精通iOS开发--第19章 Core Location 和 Map Kit 01 Capabilities 下 示例程序
- 精通iOS开发--第19章 Core Location 和 Map Kit 上
- [精通iOS开发(第5版)]第18章 Core Location 和 Map Kit 笔记
- IOS-笔记18(Core Motion,Core Location,Map Kit)
- IOS Core Location-ios定位
- IOS开发之Core Location
- IOS开发之Core Location
- iOS开发之core location
- iOS开发之-Core Location
- 关于Core Location-ios定位
- 关于Core Location-ios定位
- 关于Core Location-ios定位
- 关于Core Location-ios定位
- 关于Core Location-ios定位
- 精通iOS开发--第15章 Grand Central Dispatch和后台处理之程序生命周期 NSNotificationCenter和线程
- iOS游戏框架Sprite Kit基础教程第1章编写第一个Sprite Kit程序
- [精通iOS开发(第5版)]第16章 使用Quartz和OpenGL绘图 笔记
- [精通iOS开发(第5版)]第17章 轻击、触摸和手势 笔记
- Java Web学习(2):静态网页与动态网页
- Android开发中图片的三级缓存
- 蒟蒻的内心独白
- JQuery学习
- 解决view 滑动事件冲突(实战篇-内部拦截法)
- 精通iOS开发--第19章 Core Location 和 Map Kit 01 Capabilities 下 示例程序
- OpenLayers2 源码解读 事件Event、Events
- git如何clone所有的远程分支
- java编码与解码
- 恢复Activity状态
- HTML的按钮,文本框等零件
- TCP/IP编程之accept函数详解
- CIFAR-10在caffe上进行训练
- MFC标题和文字的修改