iPhone实战:定位与地图

【爱思助手】iPhone虚拟定位打卡 手机虚拟定位的使用 阅读详情

个人觉得地理位置这部分的知识其实是相当有趣的。这些功能看起来是挺复杂,但在实际的开发过程中,iOS为我们封装了大部分的功能,让我们不需要学习太底层的知识。

个人觉得地理位置这部分的知识其实是相当有趣的。说到定位其实在大多数的社交软件中都有这样的一个功能,用户可以共享自己的位置并且查看其他用户的位置,从而更容易地结交一些附近或者在同一地区的朋友,又或者在地图上显示自己的当前位置,并且显示附近的餐厅或者咖啡厅。这些功能看起来是挺复杂,但在实际的开发过程中,iOS为我们封装了大部分的功能,让我们不需要学习太底层的知识,通过他提供的两个库就能轻松实现。接下来我会一步一步地讲述相关知识。

1、获取当前定位

iOS提供了一个叫作CoreLocation.framework的框架。使用他可以取到自己的定位信息(经纬度)。请参考下面代码片段:

if([CLLocationManager locationServicesEnabled]){
        //定位功能开启的情况下进行定位
        CLLocationManager *manager = [[CLLocationManager alloc] init];
        manager.distanceFilter = kCLDistanceFilterNone;
        manager.desiredAccuracy = kCLLocationAccuracyBest;
        manager.delegate = self;
        [manager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation
{
    
    [manager stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager 
       didFailWithError:(NSError *)error
{
    [manager stopUpdatingLocation];
}

如上面代码所示CLLocationManager就是用于获取定位信息对象类,在实际应用中可以根据自己的需要来设置定位的更新频率以及定位准确度。其中代码中的distanceFilter表示更新位置的距离,假如超过设定值则进行定位更新,否则不更新。代码中的kCLDistanceFilterNone表示不设置距离过滤,即随时更新地理位置。desiredAccuracy属性表示取得定位的精度,kCLLocationAccuracyBest表示最精确,但也预示着需要消耗更多的时间和电量,所以应该根据需要设定。

那么CLLocationManager是通过什么方法来开启定位的呢?他是通过调用startUpdatingLocation开启定位功能,然后使用stopUpdatingLocation停止定位,其中定位信息是通过loctionManager:didUpdateToLocation:fromLocation;委托方法来通知委托对象的,因此委托对象必须实现CLLocationManagerDelegate委托。在返回定位信息委托方法中主要的两个参数是newLocation和oldLocation,newLocation表示最新定位,oldLocation表示上一次的定位信息。这两个都是CLLocation对象。以下是CLLocation的属性说明:

属性描述
altitude海拔高度
coordinate经纬度
course行驶方向
horizontalAccuracy水平方向的精确度
Speed行驶速度
timestamp时间戳
verticalAccuracy垂直方向的精确度

2、获取地理位置信息

当你取到了一个经纬度信息时,也许还有这样的一个需求,那就是当前的经纬度所对应的地理位置信息是什么。那么这时候我们需要用到框架来为我们实现这一功能,那就是MapKit.framework。在这个框架中有一个叫MKReverseGeocoder的类可以帮助我们实现反向解析地理位置。请看一下代码:

-  (void)locationManager:(CLLocationManager *)manager 
     didUpdateToLocation:(CLLocation *)newLocation 
            fromLocation:(CLLocation *)oldLocation
{
    MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];     
    geocoder.delegate = self;     
    [geocoder start];
}

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder 
       didFindPlacemark:(MKPlacemark *)placemark
{
     NSLog(@"\n country:%@\n postalCode:%@\n ISOcountryCode:%@\n locality:%@\n subLocality:%@\n administrativeArea:%@\n subAdministrativeArea:%@\n thoroughfare:%@\n subThoroughfare:%@\n",
           placemark.country,           
           placemark.postalCode,           
           placemark.ISOcountryCode,           
           placemark.administrativeArea,            
           placemark.subAdministrativeArea,           
           placemark.locality,           
           placemark.subLocality,           
           placemark.thoroughfare,
           placemark.subThoroughfare); 
}  

-  (void)reverseGeocoder:(MKReverseGeocoder *)geocoder 
        didFailWithError:(NSError *)error
{     
    NSLog(@"reverse geocoder fail!!"); 
}

上面的代码是在获取到经纬度后,立刻进行反向地理位置解析的。其实MKReverseGeocoder用法也比较简单,通过经纬度初始化后直接调用start方法就可以实现反向解析了,然后等待返回,其返回是通过委托形式通知的。所以委托对象必须实现MKReverseGeocoderDelegate委托。解析成功后会返回一个MKPlacemark的对象里面包含了相关的地理位置信息(包括国家、地区、街道等)。

但从iOS5之后MKReverseGeocoder成为了不推荐使用的类。因此有一个新的类取代了他的作用,那就是CLGeocoder类,使用该类进行反向解析也非常容易,请看下面代码:

CLGeocoder *geocoder=[[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:newLocation                     
               completionHandler:^(NSArray *placemarks,
                                   NSError *error)
               {                        
                       CLPlacemark *placemark=[placemarks objectAtIndex:0];            
                       NSLog(@"name:%@\n country:%@\n postalCode:%@\n ISOcountryCode:%@\n ocean:%@\n inlandWater:%@\n locality:%@\n subLocality:%@
\n administrativeArea:%@\n subAdministrativeArea:%@\n thoroughfare:%@\n subThoroughfare:%@\n",
                              placemark.name,
                              placemark.country,
                              placemark.postalCode,
                              placemark.ISOcountryCode,
                              placemark.ocean,
                              placemark.inlandWater,
                              placemark.administrativeArea,
                              placemark.subAdministrativeArea,
                              placemark.locality,
                              placemark.subLocality,
                              placemark.thoroughfare,
                              placemark.subThoroughfare);
              }]; 

从代码来看,CLGeocoder类没有使用委托的形式通知返回状态,而是通过block的方式进行回调,而且MKReverseGeocoder委托只返回了一个地标位置,但是CLGeocoder则返回了一个包含多个地标位置的数组,但这个数组在通常状态下是只有一个元素,如果存在多个元素那证明了给定解析的经纬度被解析到多个不同的地标信息。如果解析错误或者调用cancel方法则此参数为nil。

3、地图显示

想更加形象地表现出位置信息靠文字的描述是远远不够的,因为使用地图来显示地理位置将会给用户带来全新的体验。在iOS里面已经将Google地图封装到SDK里面了,我们可以用很少的代码来实现很多在地图上的操作(如标记位置、绘画线路等)。下面的代码是生成一张地图并显示到界面上:

-  (void)viewDidLoad
{
	[super viewDidLoad];
        MKMapView *mapView=[[MKMapView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)]; 	  
        mapView.delegate = self;
        [self.view addSubview:mapView];
        [mapView release];
}

这够简单吧,上面的设置地图委托对象是因为在下面要标记地理位置时需要用到的。那么如何把取到的经纬度信息显示到地图上呢?其实每个坐标信息在地图中显示后都对应一个MKAnnotationView,而MKAnnotationView又负责解析了一个实现MKAnnotation协议的数据对象。因此我们首先要做的事情就是把取到的经纬度转换为MKAnnotation协议对象。先定义一个实现MKAnnotation协议的类:

@interface  DemoAnnotation : NSObject<MKAnnotation> {
	CLLocationCoordinate2D _coordinate;
}

-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;

@end 

@implementation DemoAnnotation

@synthesize coordinate=_coordinate;

-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate{
	if (self = [super init]) {
		_coordinate=coordinate;
	}
	return self;
}

-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate{
	_coordinate=newCoordinate;
}

-(NSString *)title{
	return @”我的位置”;
}

-(NSString *)subtitle{
	return nil;
}

@end 

上面的类只是简单地保存了经纬度信息。记得注意的是MKAnnotation协议中的title和subtitle的作用,如果你在显示AnnotationView设置其canShowCallout属性为YES时,则当用户点击AnnotationView时会弹出一个Callout视图,用于显示title和subtitle,假如设置title为nil那么即使canShowCallout为YES也不会弹出Callout视图。

接下来要改写一下获取定位成功后的方法,等待获取定位成功后把经纬度设置到地图上显示。实现代码如下:

-  (void)locationManager:(CLLocationManager *)manager 
     didUpdateToLocation:(CLLocation *)newLocation 
            fromLocation:(CLLocation *)oldLocation
{
	DemoAnnotation *annotation = [[DemoAnnotation alloc] initWithCoordinate:newLocation.coordinate];
	[_mapView addAnnotation:annotation];
	[annotation release];

	MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];     
        geocoder.delegate = self;     
        [geocoder start];
}

上述代码中加粗部分的代码就是把经纬度信息封装到刚才定义好的对象中。然后通过addAnnotation方法传递给MapView;这里的_mapView是把之前viewDidLoad方法中的临时变量改变为类属性以达到跨方法引用的目的。经过上面步骤已经把我的位置引入到地图里面了,但现在还不会显示在地图上,因为还需要实现MapView中的协议,告诉MapView如何显示你Annotation。以下代码采用iOS中默认的大头针样式来显示位置。如下:

-  (MKAnnotationView *)mapView:(MKMapView *)mapView 
             viewForAnnotation:(id <MKAnnotation>)annotation
{
    NSString *annotationViewId=@"CurrentUserAnnotationView";
    MKPinAnnotationView *annotationView = (MKPinAnnotationView *)
    [mapView dequeueReusableAnnotationViewWithIdentifier:annotationViewId];
    if (annotationView==nil)
    {
        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationViewId] autorelease];
	annotationView.canShowCallout = YES;
    }
    return annotationView;
}

上面的协议方法就是MapView告诉你他需要显示哪个annotation,然后显示的样式由用户你自己决定,但必须要继承MKAnnotationView类。

到这里对于定位和地图的应用就告一段落了,当然关于 MKMapView 还有一些更加高级的特性,例如:动态编辑 Annotation 、绘画路线图等应用我在这里暂时不说了,等偶再研究透彻一点再给大家分享。

iPhone模拟定位(非越狱修改手机定位) 剩下的事情就是build一下到手机,那么,就可以看到神奇的效果! 本次带来一个简单又好玩的实用功能,比如定位装逼(共享定位非分享可选那种),又或者定位打卡之类,由于改变的是设备级别的定位,本设备所有地图定位APP都可以修改,钉钉的定位打卡自测也可以,操作的简单性连一行代码都不需要。对于iOS developer来说,装备简直毫无门槛,仅需要2样: 一台装有Xco... 阅读详情

相关推荐

Vim 入门到够用:Linux 文本编辑器的三种模式、常用操作与实战技巧

i 进入编辑模式Esc 退出编辑模式回到命令模式: 从命令模式进入底行模式编辑,不一定非得“打开就直接打字”。一旦你接受了“模式”这件事,后面很多操作都会顺起来。学 Vim,不要追求一次学全,先把“命令模式—编辑模式—底行模式”这条主线练熟。只要这条主线通了,后面的复制、删除、搜索、替换,都是顺手补上去的能力。

Web安全工具库 800

xiao77论坛php,论坛

论坛1. 如何加其他人为好友?ID头像下方有“加好友”、“发消息”、“打招呼”和“串个门”的互动功能。在发帖的头像区和该人的个人资料区都可以进行互动,且有不同的奖励。 2.看到喜欢的帖子如何保存?可点击帖子下方的“收藏”按钮,然后回到个人空间的收藏应用中查看即可。 3.如何查看所有我参与过的帖子?登录成功后,在页面右上角点击“帖子”即可查看。 4.如何知道我参与的帖子有了新的回复?当有人回复了你的...

weixin_39614109的博客 65万+

Matlab实战:水声信号DEMON谱分析从入门到精通(附完整源码)

本文详细介绍了使用Matlab进行水声信号DEMON谱分析的完整流程,从基础理论到实战应用,涵盖信号预处理、包络提取、频谱分析等关键步骤,并附完整源码。特别针对水声通信中的低信噪比环境,提供了多种优化方案和性能提升技巧,帮助读者快速掌握这一水下目标检测的核心技术。

gamma的博客 296

纠缠在回忆里的感伤

  一个身影从眼前晃过,我本能的踩死了刹车,车因为惯性向前使了一点后终于停了下来,幸亏没有撞到那个骑车的老人!我尚惊魂未定,额头冒出了冷汗,好险!    人在开车心却早就离开了心脏,鬼使神差,我又在以前的世界里挣扎。虽然努力克制,虽然试图忘记,原来,自己真的是世界上最没用最没用的家伙!眼角,泪悄然落下。问自己为什么要这般傻问自己为什么还是放不下?不是找不到答案,只是答案太真现实太残酷自己太无助!走

xiao77777的专栏 4万+

《UDS协议从入门到精通》系列——图解0x38:请求文件传输

详细解释UDS协议中0x38-请求上传服务的各个参数!!

车载系统攻城狮 3267

【ComfyUI】SD1.5 + ControlNet 边缘检测融合动漫转真人

本文介绍了一个基于ComfyUI的动漫转真人图像生成工作流,通过多模型协同实现高质量的二次元图像转换。该工作流集成了Canny线稿预处理、ControlNet结构控制、VAE编码解码和人脸精细化处理等核心环节,采用majicmixRealistic_v7作为主模型,配合yolov8、SAM等辅助模型。整个流程包含11个标准化步骤,从图像输入、预处理到最终超分输出,通过ControlNet引导和CLIP语义控制确保生成图像的写实感和结构准确性,特别针对人脸区域进行专业优化,最终可输出高分辨率写实人像。

Mr数据杨 1126

Welcome to Xiao

这里写自定义目录标题Welcome to Xiao新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 Welcome to Xiao 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

xiao_123_123的博客 5万+

YOLOv11 改进入门篇 | 从原理到代码:CBAM 注意力模块的插入与涨点验证

本文介绍了如何在YOLOv11模型中插入CBAM注意力模块以提升检测性能。CBAM包含通道和空间注意力两个子模块,通过双池化操作和MLP学习特征权重。文章详细解析了CBAM原理,提供了PyTorch实现代码,并建议在YOLOv11的Stage-3和Stage-4之间插入CBAM。实验表明,该方法在COCO数据集上使nano和small模型的mAP提升1.7-2.3个百分点,参数量仅增加0.27%,推理延迟增加0.1ms。最后给出了插入位置选择、通道缩减比等调优建议,验证了CBAM作为轻量级注意力模块的有效性

shrgegrb的博客 1301

【leetcode】【77】Combinations

一、问题描述 Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For example, If n = 4 and k = 2, a solution is: [ [2,4], [3,4], [2,3], [1,2], [1,3]

斗code、年华 4万+

NR TA

这篇是NR TA的笔记,之前有对R17 NTN TA进行了简单总结,但是也仅仅局限在NTN部分,其他TA基本过程没有涉及,这篇是针对R16版本协议对NR TA相关内容做的总结。和PUSCH power control过程类似,NR TA也可以分为开环 和闭环调整,相关内容分散在38.300,38.211,38.213,38.321,38.133和38.331。后面就按照38.300 TA相关概念,38.211中有关TA定义,38.213 TA 相关内容,38.321 TA控制过程,38.133 Timi

ModemProtocol的博客 769

【通信】多径衰落信道的matlab仿真

1 简介 2 部分代码 clearf_c=1e3; %carrier frequency(no modulation)time_1 = (linspace (0, 10, 1000)); %timesignal_in = sin (2 * pi *f_c* time_1); %sine wave plot (time_1, signal_in, 'b');grid on;

qq_59747472的博客 1383

今儿下午疲惫极了

回家的公车上人也特别的多,春天来了,气温渐温,街上的颜色也丰富起来,我一路的走,一路的观望,看着一张张的笑脸,我也一路的想,想我爱的人和爱我的人,不觉得走神了。下车没两步,我摔了一交,结结实实的。手中的电脑包抛了老远,我一下子倒在了路边,脑子嗡响了一下,暂时的记忆就没了。大约有那么两三秒,也许是我摔倒的动静太大了,感觉周围的目光都在朝我这边看,一时间的尴尬,没顾得上身上的土,站起来就往住的方向猛走

xiao7733bbb的专栏 3万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【转载】iPhone实战:定位与地图

今天在CocoaChina上发现一篇讲定位与地图的教程,感觉写的比较透彻,通过阅读该文会对定位相关的各个类和协议有更清晰的认识,现将链接记于此,备用。iPhone实战:定位与地图  ...

iOS杨叫兽技术博客 160

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

iPhone开发实战:定位与地图

个人觉得地理位置这部分的知识其实是相当有趣的。说到定位其实在大多数的社交软件中都有这样的一个功能,用户可以共享自己的位置并且查看其他用户的位置,从而更容易地结交一些附近或者在同一地区的朋友,又或者在地图上显示自己的当前位置,并且显示附近的餐厅或者咖啡厅。这些功能看起来是挺复杂,但在实际的开发过程中,iOS为我们封装了大部分的功能,让我们不需要学习太底层的知识,通过他提供的两个库就能轻松实现。接下来

M_baronJJ的专栏 1107

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 在 Windows 上安装和使用 GNUstep 和 Objective-C
下一篇: 使用 Collections.frequency 找出重复的单词
meng0911
博客等级 码龄15年 15粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值