SwiftUI 是一种非常简单的创新方法,可以利用 Swift 的强大能力在所有苹果设备平台上构建用户界面。通过 SwiftUI,开发者仅使用一组工具和 API 就能为所有苹果设备构建用户界面。SwiftUI 使用易于阅读和编写的声明式 Swift 语法,可与新的 Xcode 设计工具无缝协作,使你的代码和设计完美同步。SwiftUI 自动支持动态类型、深色模式、本地化和可访问性,你的 SwiftUI 代码将成为你写过的最强大的 UI 代码。
目标
实现一个列表,点击列表的 item,跳转到对应的详情页。
根据苹果官方教程,整理了 SwiftUI Sample。
首先回想一下在 UIKit 中如何实现:
- 创建一个带导航 Navigation 的 controller,用来布局和 Push 下一个页面。
- 添加 UITableView,并实现 UITableView 的两个代理方法,展示列表。
- 创建 UITableViewCell,布局 UILabel 和 UIImageView。
创建详情页面,布局地图、三个 UIlabel。 - 在 UITableViewDelegate 的代理方法中 Push 到详情页。
- 对 iOS 开发来说这太简单太熟悉不过了,但很多代码比较繁琐,控件的创建、布局等。虽然简单,但繁琐,浪费了很多本该花在业务上的时间。
在 SwiftUI 中怎么实现呢?
在实现之前,先看一下所需要的组件,按照用途大致分为基础组件、布局组件和功能性组件,以及 XCode11 提供的新功能。
所需组件
基础组件
-
Text
用来显示文字 类似于 UIKit 中的UILabel
-
Image
用来显示图片 类似于 UIKit 中的UIImageView
-
Spacer
用来填充空白
布局组件
-
VStack
竖直摆放的组合组件 -
HStack
水平摆放的组合组件 -
List
用来展示列表 类似于 UIKit 中的UITableView
功能型组件
NavigationView
展示导航栏类似于 UINavigationBar
NavigationLink
类似于 pushViewController:
方法
XCode11相关功能
预览
实时看到对页面的做出的修改
- 纯 SwiftUI 时,默认静态预览。
点击预览串口的 Resume 按钮。
如果没有显示预览窗口,则按下图操作打开。
- 预览包含 UIView 子类视图时,需要打开时时预览
点击可以切换时时预览和静态预览。
拖放
command 键 + 鼠标点击组件,可以方便的添加组件,设置组件属性等。
代码实现
创建列表
struct LandmarkList : View {
var body: some View {
// 自定义显示的内容
List(0 ..< 5) { item in
Text("hello")
.font(.title)
}
}
}
使用 List
组件可以快速的创建滑动列表,不需要设置代理,不需要实现协议方法就达到类似于 UIKit 中 UITableView
的效果。
Text
用来展示文字,通过 .font
设置了字体大小。将它放入 List
中,它就是列表的 Item。
从工程 Resources 文件夹中找到资源文件,引入工程,里面包含了 json 数据、图片等。再引入 Models 文件夹中的 Data.swift
和 Landmark.swift
,这些主要是为了组件数据和 Model,不是本文讨论的重点,下面会用到这些数据。
创建 Item
这一步在 UIKit 中像自定义 UITableViewCell,需要再其中添加一个图片和一个文字。
在 SwiftUI 中,没有 UITableViewCell 的概念,需要显示一行的时候,只需要使用 HStack
组件,HStack
组件是一个组合组件,其中可以放 Text
、Image
等组件。
创建 LandmarkRow
struct LandmarkRow : View {
var landmark: Landmark
var body: some View {
HStack {
landmark.image(forSize: 50)
Text(landmark.name)
}
}
}
landmark.image(forSize: 50)
这个方法返回一个指定大小的图片
Text
显示地标名称。
HStack
将图片和文字组合在一行里面显示,并配置的有默认格式。
效果:
把它带入第一步创建的列表中,并引入数据。
struct LandmarkList : View {
var body: some View {
List(landmarkData) { landmark in
LandmarkRow(landmark: landmark)
}
}
}
效果:
列表已经显示出来了。
想想 UIKit 中的那堆代码,是不是暗爽?
创建详情页
从效果图中看到详情页有一个地图、一个圆形图片、几个显示地名、位置的文字。
从布局上看最下面两个水平的文字可以摆放在水平组件中,再和标题文字一起摆放在竖直组件中。
地图、图片、水平摆放的组件再一起摆放在竖直摆放组件中。
创建地图模块:
struct MapView : UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
要在 SwiftUI 中添加非 SwiftUI 的组件,需要遵循 UIViewRepresentable
协议,并实现协议方法。
创建圆角图片:
struct CircleImage : View {
var image: Image
var body: some View {
image
.clipShape(Circle())
.overlay(
Circle().stroke(Color.white, lineWidth: 4)
.shadow(radius: 10)
)
}
}
创建详情页
struct LandMarkDetail : View {
var landmark : Landmark
var body: some View {
VStack {
MapView(coordinate: landmark.locationCoordinate).frame(height: 300)
CircleImage(image: landmark.image(forSize: 250))
.offset(y: -130)
.padding(.bottom, -130)
// 三个文字
VStack(alignment: .leading) {
Text(landmark.name)
.font(.title)
// 下面两个文字
HStack {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
}
.padding()
Spacer()
}
}
}
VStack
竖直组合组件,里面包含了 MapView
和 CircleImage
以及 VStack
。
VStack
中包含了标题文字以及HStack
。
HStack
中包含了水平摆放的两个文字组件。
效果:
实现跳转
上面已经分别实现了列表页和详情页面,下面实现跳转。
UIKit 中想要 Push 效果需要创建 UINavigationController ,想要显示导航栏需要设置 UINavigationBar,想要跳转需要在 UITableView 的代理方法中调用 pushViewController:
方法。
修改上面创建的列表:
struct LandmarkList : View {
var body: some View {
NavigationView {
List(landmarkData) { landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
.navigationBarTitle(Text("Landmarks"), displayMode: .inline)
}
}
}
NavigationView
组件类似于 UINavigationBar,可以设置导航栏标题和模式。
NavigationLink
可以直接将跳转方法直接和列表展示绑定在一起,逻辑更清晰明了。
总结
了解过 Flutter
的同学对这个接受可能会很快。
没有了解过 Flutter
的同学需要转变一下页面布局思路。
SwiftUI 对 iOS 开发同学来是一大福音,毕竟都2019年了,还在使用 UIKit 中这么原始的布局,实在是苦不堪言。
SwiftUI 需要 iOS13 以上的系统,但目前公司开发 App 都会支持一定的老版本系统,还得使用 UIKit。全面使用 SwiftUI 预计还有一段时间。毕竟,还有很多公司没有使用 Swift 呢。
写的有不好的地方希望大家指出,我会更正,大家有什么看不明白的,也可以在评论里面提问,我会尽力解答。另附 Apple 官方 SwiftUI Tutorials。
点赞+关注,第一时间获取技术干货和最新知识点,谢谢你的支持!
最后祝大家生活愉快~