热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MapKit使用介绍:大头针和图形渲染

作者:PRANJALSATIJA,原文链接,原文日期:2016-11-13译者:TonyHan;

作者:PRANJAL SATIJA,原文链接,原文日期:2016-11-13
译者:TonyHan;校对:Cwift;定稿:CMB

最近 APP 中的地图功能变得越来越流行了。从优步到 Instagram ,再到我的新应用 peek ,地图功能在各种 APP 中都能见到。虽然地图很常见,但是往地图功能添加一些更复杂的功能还是有点挑战的。在这篇文章中,咱们就讨论下在 MapKit 中的大头针和图形渲染,MapKit 是苹果 iOS 系统中的地图库。你在 iOS 系统中看到的许多地图都依赖 MapKit 的强大支撑——当然包括苹果内置地图 APP!MapKit 是一个功能强大、稳定的、健壮的地图库。当然它也很易用,让我们开始吧!

准备工作

开始之前,请先下载实例程序。打开之后你会发现这些文件:

  • Places.plist:这是存储我们要渲染的坐标信息的配置文件。

  • Places.swift:这个 swift 文件加载 Places.plist 文件中的数据并暴露给其他代码。

  • Main.storyboard:这是我们应用使用的主 storyboard 。里面是一个带有地图视图的视图控制器。我已经搭建好界面和约束了。

  • ViewController.swift:这是用于控制地图的试图控制器。我已经创建好一个连线来连接 storyboard 中的地图视图。

在构建运行应用之前,还有一件事情需要做:导入 MapKit.framework 到我们项目中,这样才能使用 MapKit。有两种方式:一种是手动添加依赖库。点击项目导航中的 MapKit starter ,向下滚动到 Linked Frameworks and Libraries :

点击加号图标添加 MapKit.framework。如果 Embedded Binaries 中没有自动添加,则在此处也要点击加号添加。

或者,你可以去 Capabilities 界面将 Maps 选项设置为 ON

现在我们已经准备完毕!编译并运行应用看看会效果!你将会看到 MKMapView 占据了整个屏幕。默认情况下,地图视图支持放大、旋转、滚动以及 3D 模式。它还显示有趣的地点,并在主要城市以 3D 显示建筑物。相当酷吧!这篇文章中我们将使用这个地图,泡杯咖啡坐下来,一起进行这项工作吧!

用户坐标展示

首先,将用户的坐标展示到地图上是很重要的,这样用户就可以对其所在位置周围的建筑有所感知。很幸运,用 MapKit 很容易做到这一点。打开 Storyboard,选择我们的地图,勾选 User Location 这一项:

如果你想通过代码实现,把下面这一行放到控制器中的 viewDidLoad 方法中:


mapView?.showsUserLocation = true

在达到目标前还有几步要完成。现在,MapKit 将会展示用户的位置,但我们还没有申请用户授权。我们来完成这个。

打开 ViewController.swift 并且添加一个方法 requestLocationAccess():


func requestLocationAccess() {let status = CLLocationManager.authorizationStatus()switch status {case .authorizedAlways, .authorizedWhenInUse:returncase .denied, .restricted:print("location access denied")default:locationManager.requestWhenInUseAuthorization()}
}

这个方法实现一个简单的目标:检查用户是否授权使用位置并作出响应。如果用户已经授权过,那直接返回,不再有其他操作。如果用户拒绝或限制位置信息使用,则会输出错误信息。否则,我们在应用中会向用户申请使用位置信息。

最后一件事。找到 Info.plist 文件。增加一个类型为 String 的键 NSLocationWhenInUseUsageDescription,然后设置值为 MapKit starter needs your location so that you can see it on a map.。通过这个可以告诉用户我们为什么要去请求使用位置信息,从而让用户更倾向于同意访问。从 iOS 8 开始,系统要求我们必须添加这段字符信息。

还有一步!在 ViewController.swift 中重写 viewDidLoad() 方法并调用 requestLocationAccess() 方法:


override func viewDidLoad() {requestLocationAccess()
}

再一次编译并运行应用。你会得到一个获取用户信息的提示。点击接受,然后看着吧。现在会显示出你所在的位置。MapKit 会随着用户位置的移动而自动更新坐标。

如果你在用模拟器测试应用,你可以点击调试区域的位置按钮,Xcode 提供了一系列位置信息来模拟用户的位置。

现在让我们试试显示更牛逼的内容吧。

展示自定义大头针

我们已经知道如何展示用户的坐标了,但是现在,我们需要展示用我们的自己的图片自定义的大头针样式。打开 Places.plist 文件,查看其内容。你能看到一个简短的城市列表。由于只是个例子,我们并没有准备太多数据。

html



titleNew YorkdescriptionWelcome to New York City!latitude40.7128longitude-74.0059titleSan FranciscodescriptionWelcome to San Francisco!latitude37.7749longitude-122.4194titleLos AngelesdescriptionWelcome to Los Angeles!latitude34.0522longitude-118.2437


列表里有纽约、旧金山和洛杉矶及其经纬度坐标。虽然有关配置文件的知识已经超出了本篇教程的范围,但是你可以在这篇文章里找到关于 .plist 配置文件的内容。

打开 Places.swift 文件,你会看到一个静态方法,用来获取 Places.plist 文件中的所有地点。你不用关心实现,你只需要去调用 Place.getPlaces() 方法,便可以返回 Places.plist 中的所有地点。让我们在 ViewController 中添加一个属性,用来保存所有已加载的地点信息:


let places = Place.getPlaces()

确保 ViewController.swift 中的代码如下:


import UIKit
import MapKitclass ViewController: UIViewController {@IBOutlet var mapView: MKMapView?let locationManager = CLLocationManager()let places = Place.getPlaces()override func viewDidLoad() {requestLocationAccess()}func requestLocationAccess() {let status = CLLocationManager.authorizationStatus()switch status {case .authorizedAlways, .authorizedWhenInUse:returncase .denied, .restricted:print("location access denied")default:locationManager.requestWhenInUseAuthorization()}}
}

现在,让我们看看关键的地方。下面是在 MKMapView 上添加大头针的基本流程:

  1. 创建遵从 MKAnnotation 协议的对象,扩展已存在的对象也可以。

  2. 通过 addAnnotation(_:) 在一个 MKMapView 实例中添加大头针对象。

  3. 创建遵从 MKMapViewDelegate 协议的对象并指定其代理为我们的地图视图。

  4. 实现 mapView(_: viewFor:) 方法,为 MapKit 提供需要渲染的大头针视图。

下面我们会实现上面的四个步骤。

创建遵从 MKAnnotation 协议的对象

MKAnnotation 协议定义在 MapKit 中,用来给 MapKit 提供数据。我们来实现 MKAnnotation 协议的要求:


var title: String?
var subtitle: String?
var location: CLLocationCoordinate2D

任何用来保存或展示大头针的自定义对象都可以通过遵守 MKAnnotation 协议从而使用相关的功能。随后每个对象都会作为地图上大头针的数据源,提供关键的信息,比如大头针在地图上的位置。

如你所料,我们扩展 Place 类并遵从 MKAnnotation 协议。在 Place.swift 中导入 MapKit 并添加 MKAnnotation 协议:


extension Place: MKAnnotation { }

编译并运行,啥东西也没有。这是正常的。同时,我们的 Place 类也已满足 MKAnnotation 的所有的要求。

很好。让我们接着做下一步。

向地图视图添加大头针

这步不难。我们只需要告诉 mapView 我们已经加载的每一个地点即可。在 ViewController.swift 中添加一个方法。命名为 addAnnotations():


func addAnnotations() {mapView?.delegate = selfmapView?.addAnnotations(places)
}

这并不复杂。将地图视图的代理设置成 self。然后,我们将地点大头针添加到地图上。简单吧!继续之前记得在 viewDidLoad() 中调用 addAnnotations() 方法。

遵守 MKMapViewDelegate 协议

接下来我们需要创建一个遵守 MKMapViewDelegate 协议的对象。跟 MKAnnotation 协议一样,我们需要扩展一个类来实现。如果你之前用过 UITableView,那这跟使用 UITableViewDelegateUITableViewDataSource 相似。我们使用 ViewController 的扩展来实现 MKMapViewDelegate 协议:


extension ViewController: MKMapViewDelegate {func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {}
}

上面的代码扩展了 ViewController 类,并且添加了向每个大头针返回相应视图的方法。让我们继续:


func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {if annotation is MKUserLocation {return nil}else {let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationView") ?? MKAnnotationView()annotationView.image = UIImage(named: "place icon")return annotationView}
}

很简单是吧?首先我们检查一下大头针是否展示在了用户位置上。如果是,我们不用返回自定义大头针,因为我们希望和往常一样来展示用户的位置。如果没有的话,我们新建一个大头针,我们通过 **[复用队列
](https://en.wiktionary.org/wik...** 来创建一个新的大头针。这样我们就能有效的复用大头针视图。然后,我们设置大头针视图上的图片(在 Assets.xcassets 中使用的图片)。最后,我们返回大头针视图。

审查代码

看下 ViewController.swift 文件。如果你按照步骤做完,那代码应该是这样的:


import UIKit
import MapKitclass ViewController: UIViewController {@IBOutlet var mapView: MKMapView?let locationManager = CLLocationManager()let places = Place.getPlaces()override func viewDidLoad() {requestLocationAccess()addAnnotations()}func requestLocationAccess() {let status = CLLocationManager.authorizationStatus()switch status {case .authorizedAlways, .authorizedWhenInUse:returncase .denied, .restricted:print("location access denied")default:locationManager.requestWhenInUseAuthorization()}}func addAnnotations() {mapView?.delegate = selfmapView?.addAnnotations(places)}
}extension ViewController: MKMapViewDelegate {func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {if annotation is MKUserLocation {return nil}else {let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationView") ?? MKAnnotationView()annotationView.image = UIImage(named: "place icon")return annotationView}}
}

运行应用,你会发现地图中有三个大头针分别对应 Place.plist 文件中指定的地点。

如果没成功,请往前查看是否遗漏了某一步。如果需要帮助请随时留言。现在我们已经掌握了向 MKMapView 添加了大头针的技巧。peek 中就是用这样的方式向用户展示事件发生的位置。大多数带地图功能的应用都使用这个技术来向用户展示指定的地点。

现在我们来看看如何添加图层渲染。

展示图层渲染

目前为止,我们已经学会如何展示自定义的大头针以便标注出地图上的地点。接下来我们来学习在地图上绘出图形。例如,我们可能会在每个地点周围画出半径 100 米圆。为了实现这点,我们需要做两件事:

1.在我们的地图上添加遮罩。
2.为每个遮罩指定渲染器,让 MapKit 去渲染这些图层。

添加遮罩

首先,需要告诉 MapKit 我们想在地图上展示遮罩。修改 addAnnotations(),如下:


func addAnnotations() {mapView?.delegate = selfmapView?.addAnnotations(places)let overlays = places.map { MKCircle(center: $0.coordinate, radius: 100) }mapView?.addOverlays(overlays)
}

前两行很相似,后面两行代码是新的。我们使用 map —— Swift 的集合操作函数,来生成一个基于我们的地点的 MKCircle 对象数组。如果你对 map 感到陌生,可以理解为 for 循环。但是你可以一行代码实现。

接下来,通过 mapView?.addOverlays(_:) 添加遮罩。跟添加大头针类似。

渲染遮罩

添加遮罩还不够。你只有渲染并设置可见,MapKit 才会去显示这些遮罩。我们对每个地点添加了圆形的遮罩,对应地要对遮罩进行渲染。在 ViewController 扩展中添加 mapView(_: rendererFor:) 方法:


func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {let renderer = MKCircleRenderer(overlay: overlay)renderer.fillColor = UIColor.black.withAlphaComponent(0.5)renderer.strokeColor = UIColor.bluerenderer.lineWidth = 2return renderer
}

正如名字所显示的,这个方法允许我们返回 MKOverlayRenderer ,为每个遮罩提供合适的渲染。MapKit 对于圆形的渲染有一个类,叫做 MKCircleRenderer。我们创建一个渲染器,并且设置成想要的外观,并将其返回, MapKit 就可以使用渲染器了。

现在你可以再次测试应用。放大纽约、旧金山或洛杉矶,能看到圆形的遮罩。

总结

通过这篇文章我们学到了很多关于大头针和图形渲染的知识。用这些知识武装自己,你应该能够开发一个带有优雅地图的应用了吧!有啥问题随时都可以评论。

另外,你可以从 GitHub 上下载 Xcode 项目来参考。

本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 http://swift.gg。




推荐阅读
  • 2023年,Android开发前景如何?25岁还能转行吗?
    近期,关于Android开发行业的讨论在多个平台上热度不减,许多人担忧其未来发展。本文将探讨当前Android开发市场的现状、薪资水平及职业选择建议。 ... [详细]
  • 第六章:枚举类型与switch结构的应用分析
    第六章深入探讨了枚举类型与 `switch` 结构在编程中的应用。枚举类型(`enum`)是一种将一组相关常量组织在一起的数据类型,广泛存在于多种编程语言中。例如,在 Cocoa 框架中,处理文本对齐时常用 `NSTextAlignment` 枚举来表示不同的对齐方式。通过结合 `switch` 结构,可以更清晰、高效地实现基于枚举值的逻辑分支,提高代码的可读性和维护性。 ... [详细]
  • 在iOS6之后,不再使用谷歌地图了,而是使用苹果自己的地图,但是API编程接口没有太大的变化。开发人员不需要再学习很多新东西就能开发地图应用,这是负责任的做法。因此本节介绍的内容也同样适用于iOS5 ... [详细]
  • IOS9之当前位置定位
    2019独角兽企业重金招聘Python工程师标准#import*.h文件中导入以下两个框架*#import ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了iOS核心笔记—CoreLocation框架-基础相关的知识,希望对你有一定的参考价值。1、 ... [详细]
  • 在尝试加载支持推送通知的iOS应用程序的Ad Hoc构建时,遇到了‘no valid aps-environment entitlement found for application’的错误提示。本文将探讨此错误的原因及多种可能的解决方案。 ... [详细]
  • [译]  OS X 和 iOS 的测绘框架Core Plot 入门教程
    [译] OS X 和 iOS 的测绘框架Core Plot 入门教程 ... [详细]
  • iOS——应用内调用Face ID、Touch ID
    注意到很多iOS非原生应用都在应用内调用了FaceID,以来辅助登陆和进行隐私操作的确认,下面是如何调用FaceID或TouchID。获取用户隐私权限 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • 添加#import头文件倒入mapkit.framework库mapkit.framework是属于ui,可以在故事版上添加mkmap ... [详细]
  • IOS笔记汇总为了方便开发者开发出强大的功能,苹果提供了各种各样的框架IOS属性IOS基础属性导入依赖propertyNSStringNSDictionaryNSAr ... [详细]
  • 高德IOS真机调试LMAMapKit出错问题的解决方法(directory not found for option)
    1最近项目到了收尾阶段,所以开始了在真机部署调试,之前的模拟器环境下测试项目,一切都没问题,今天真机调试过程中, ... [详细]
  • MRMapViewController.mCoreLocation&MapKitCreatedbyMr.Roboton201786. ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
author-avatar
夜幕下的猫眼_398
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有