SwiftUI:集成 MapKit
自从2007年第一台设备问世以来,地图就一直是iPhone的核心功能,开发者几乎已经可以使用底层框架了。它叫做 MapKit,和UIKit一样,如果我们不介意进行其他工作,我们可以在SwiftUI中使用它——是的,这确实意味着使用协调器。
让我们从简单的事情开始,然后逐步发展。新建一个名为“ MapView”的SwiftUI视图,然后在顶部添加 MapKit 的导入。这次我们不会使用 UIViewControllerRepresentable
协议,因为MapKit不使用视图控制器。
一种经典的软件构建方式称为“ MVC”,它将我们的代码分为三种类型:对象模型(我们的数据),视图(我们的布局)和控制器(连接模型和视图的胶水代码)。苹果在UIKit及其包括MapKit在内的其他框架中使用了MVC,但增加了一个有趣的变化:视图控制器。他们是视图,控制器,还是两者都没有?Apple并没有真正为我们回答这个问题,这就是为什么您会在iOS应用开发中看到数百种MVC的原因。
在教UIKit时,我首先向人们解释了视图是一种布局,例如一些文本,按钮或图像,而视图控制器是内容的一个屏幕。在学习UIKit知识时,您会发现实际上可以在一个屏幕上拥有许多视图控制器,但这是学习过程中有用的心理模型。
所有这些都很重要,因为当我们使用UIImagePickerController
时,它被设计为可作为一个完整的信息屏幕使用——我们并未尝试为其添加功能,因为它被设计为可作为一个独立的单元使用。相比之下,MapKit为我们提供了MKMapView
,正如您从名称中可以看出的,这是一个视图而不是一个控制器,这意味着它仅显示我们提供给它的内容。
这就是为什么在使用 MapKit 时不使用UIViewControllerRepresentable
的原因:MKMapView
使用视图,因此我们需要使用UIViewRepresentable
。有用的工作原理几乎相同:我们需要编写称为makeUIView()
和updateUIView()
的方法,这些方法用于实例化地图视图并在SwiftUI状态更改时对其进行更新。但是,对于视图而言,此更新方法比视图控制器更为重要,因为SwiftUI代码与UIView对象之间存在更多的通信——尽管我们将该方法留给视图控制器使用,但您将在视图中使用大量此方法。
我们将很快恢复更新,但现在我们将使用另一种空方法。至于 make 方法,这将创建一个新的MKMapView
并将其返回回——我们将很快添加更多内容。
将此替换为当前的MapView
结构:
struct MapView: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<MapView>) -> MKMapView {
let mapView = MKMapView()
return mapView
}
func updateUIView(_ view: MKMapView, context: UIViewRepresentableContext<MapView>) {
}
}
在继续之前,我想向您展示一些Swift魔术。回到项目13在SwiftUI视图中包装UIViewController,当我向您介绍UIViewControllerRepresentable
协议时,我们只是短暂地使用了typealias
。这是Swift的一种让我们为现有类型创建新名称的方法,通常这样做是为了使它们更容易记住。
好吧,UIViewControllerRepresentable和UIViewRepresentable
都包含内置的类型别名。如果右键单击UIViewRepresentable
,然后选择“Jump To Definition”,则会看到SwiftUI生成的界面,它还将在UIViewRepresentable
协议中向您显示此行:
typealias Context = UIViewRepresentableContext<Self>
这将创建一个新的类型别名-类型名称-称为“上下文 Context”,无论Swift在代码中看到的Context
在哪个位置,它将认为它与UIViewRepresentableContext <Self>
相同,其中Self
是我们正在使用的任何类型。实际上,这意味着我们只能编写Context
而不是UIViewRepresentableContext <MapView>
,它们的含义完全相同。
无论如何,我们已经构建了地图视图的第一个版本,因此我们可以继续使用它。返回 ContentView.swift 并用以下内容替换文本视图:
MapView()
.edgesIgnoringSafeArea(.all)
Xcode目前无法很好地预览地图视图,因此建议您在模拟器中运行该应用以查看其外观。您应该会发现可以点击并拖动地图,但是如果按住Option键,您会看到第二根虚拟手指出现,因此您可以自由捏合和旋转。仅几行代码效果就挺好了!
当然,您真正想做的就是通过一些地标使地图栩栩如生,因此我们接下来将解决该问题……
- 即将举行的全球区块链峰会强调东西方合作
- 区块链兄弟社区问答精选:关于51%攻击,你了解有多少?
- 编程小技巧
- use vue vuex vue-router, not use webpack
- 从尾到头打印链表
- Webpack+Vue如何导入Jquery和Jquery的第三方插件
- [Hadoop大数据]——Hive部署入门教程
- Vuex原来可以这样上手
- 《Hive编程指南》—— 读后总结
- Event(事件)的传播与冒泡
- [Hadoop大数据]——Hive数据的导入导出
- 区块链技术在电子游戏与博彩行业备受追捧 有望实现数字商品货币化
- vue原来可以这样上手
- [Hadoop大数据]——Hive连接JOIN用例详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android 黑科技 |Gradle Plugin使用场景
- php5全版本绕过open_basedir读文件脚本
- CameraX 封装二维码扫描组件
- Kotlin拓展函数的真身
- 一个一年没解决的ClassNotFoundException|类加载机制探索
- 我有个大胆的方案可以提高ARouter和WMRouter的编译速度
- Tornado模板对空白字符的处理与解决方案
- View的有效曝光监控(上)|RecyclerView 篇
- PHP绕过open_basedir列目录的研究
- View的有效曝光监控(下)|ScrollView NestScrollView篇
- 聊聊AbstractProcessor和Java编译流程
- Okhttp如何开启的Http2.0
- PHP Execute Command Bypass Disable_functions
- 聊聊Android编译流程
- Android组件化问题思考