简介
SwiftUI
是Apple
推出的现代界面结构
,旨在简化界面开发和布局,并提供强大的响应式编程
和动画支撑
。与UIKit
的一个最明显的差异便是:SwiftUI
是一个纯coding
式的结构,摒弃了UIkit
的结合图形界面设计东西
构建视图的功用
概念
下面会从SwiftUI
的几个根底并且重要的知识概念出发,从而能够大致理清并了解SwiftUI 结构
的大致组成结构,到达在运用SwiftUI
这个结构时能够愈加理性的目的
- UI 控件
- 常用控件
- 控件款式
- 链式调用
- view modifier
- 动画
- 生命周期
- 视图
- 运用程序
- 适配
UI 控件
在SwiftUI
中,有许多常用的UI 控件
可用于构建运用程序的用户界面,一起还能对这些UI 控件
的款式进行调整,设计出想要的页面作用
常用控件
- Text:用于显现文本内容,支撑自定义款式、字体和颜色
- Label:用于显现带有图标的文本标签,一般用于表示标签或标题
- Button:创立一个可点击的按钮,用于执行操作或导航到其他视图
-
LinkButton:类似于
Button
,但用于打开外部链接或导航到其他运用程序 - TextField:用于接受用户的文本输入
- Image:用于显现图画,支撑本地图画和网络图画
- NavigationView:用于创立导航界面的容器
- NavigationLink:创立一个可点击的导航链接
- ScrollView:用于翻滚内容,以显现更多的信息
- List:用于显现可翻滚的列表,支撑分组和行操作
-
Form:类似于
List
,但用于创立表单布局,自动习惯键盘弹出 - Alert:用于显现警报音讯和操作
- ActionSheet:用于显现一个带有多个操作选项的弹出菜单
- VStack:垂直仓库布局,用于按垂直方向摆放视图
- HStack:水平仓库布局,用于按水平方向摆放视图
提示
-
Section
也是一个 UI 控件,可是不能独自运用,而是用于构建列表
和表格
的布局组件
。Section
一般用于将列表
或表格
中的内容分组显现
-
VStack
和HStack
是用于页面布局的,常常频频运用
控件款式
在SwiftUI
中构建用户界面时,能够运用链式调用
和封装 View Modifier
来进行款式调整。这些方法使得在不同视图上运用类似的款式变得十分快捷,一起还能够增强代码的可读性和可维护性
1. 链式调用
在SwiftUI
中,能够通过链式调用
在视图上运用多个修饰符
,从而逐步构建视图的款式。每个修饰符调用都会返回一个新的视图,能够在其上持续运用其他修饰符
struct ProfileHeaderView: View {
@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
var body: some View {
Image(avatarUrl)
.resizable()
.clipShape(Circle())
.overlay(Circle().stroke(Color.orange, lineWidth: lineWidth))
.shadow(radius: radius)
.animation(.default.repeatForever(), value: lineWidth)
.animation(.default.repeatForever(), value: radius)
.onAppear {
lineWidth = 2
radius = 4
}
.frame(width: 60, height: 60)
}
}
上面这个比如是绘制一个包括外框且有动画的头像框,能够看到首要是运用Image
这个控件来完结,外框、动画则都是对这个UI 控件
的款式进行调整,选用链式调用内置的修饰符来完结
2. 封装 View Modifier
除了运用内置的修饰符
外,您还能够创立自定义的View Modifier
,将常用的款式封装起来,以便在多个视图中重复运用,这使得你能够在代码中引进更高层次的笼统
,使得代码更具可重用性
和可维护性
struct ProfileHeaderView: View {
var body: some View {
Image(avatarUrl)
.resizable()
.circle()
.frame(width: 60, height: 60)
}
}
struct CircleModifier: ViewModifier {
@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
func body(content: Content) -> some View {
content
.clipShape(Circle())
.overlay(Circle().stroke(Color.orange, lineWidth: lineWidth))
.shadow(radius: radius)
.animation(.default.repeatForever(), value: lineWidth)
.animation(.default.repeatForever(), value: radius)
.onAppear {
lineWidth = 2
radius = 4
}
}
}
extension Image {
func circle() -> some View {
modifier(CircleModifier())
}
}
上面这个比如则是在链式调用
的根底上进行了封装,把多个款式
封装成一个款式行为,归于更高层次的款式运用。虽然完成的作用是相同的,可是当多处需要运用到上面的款式时,运用View Modifier
封装的款式能让你少写更多相同款式代码
动画
在SwiftUI
中,能够运用内置的动画功用
为UI 控件
添加动画
作用,以增强用户体验。动画
能够运用于特点的更改,从而使控件的状况转换愈加平滑和引人注目
在上面的比如中有运用到动画修饰符
,能够看到需要给动画
定义一个触发时机
运用动画有两种方法
- 动画修饰符
.animation
- 动画API
withAnimation
下面就运用之前的比如对比演示一下两者运用上的一些差异:
@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
// .animation
Image(avatarUrl)
.animation(.default.repeatForever(), value: lineWidth)
.animation(.default.repeatForever(), value: radius)
.onAppear {
lineWidth = 2
radius = 4
}
// withAnimation
Image(avatarUrl)
.onAppear {
withAnimation(.default.repeatForever()) {
lineWidth = 2
radius = 4
}
}
生命周期
SwiftUI
的生命周期与UIkit
不同挺大的,首先便是没有UIkit
那么详细的生命周期函数,然后便是SwiftUI
的生命周期分为视图
和运用程序
两种
- 视图:生命周期函数被缩减为只剩
onAppear
和onDisappear
两个 - 运用程序:生命周期与
ScenePhase
密切相关- .active:运用程序处于活动状况,即在前台运转,用户能够与运用程序进行交互
- .inactive:运用程序处于非活动状况,即在前台运转,但用户不能与运用程序交互
- .background:运用程序处于后台运转状况
SwiftUI
中运用程序生命周期
的运用案例:
struct MySwiftUIApp: App {
@Environment(\.scenePhase) private var scenePhase: ScenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { newScenePhase in
layoutWithScenePhase(newScenePhase: newScenePhase)
}
private func layoutWithScenePhase(newScenePhase: ScenePhase) {
switch newScenePhase{
case .active:
// code
case .inactive:
// code
case .background:
// code
@unknown default: break
}
}
}
}
适配
在SwiftUI
中,适配
涉及保证运用程序在不同设备
之间(如iPhone
和iPad
)以及不同屏幕尺度
和分辨率
之间都能正常显现
下面列举两个SwiftUI
针对不同设备类型的适配方案:
- Size Classes(尺度类别)
- UIDevice.current.userInterfaceIdiom
Size Classes
SwiftUI
运用尺度类别
来表示设备的巨细
和方向
,如:compact
和regular
。在视图中运用.horizontalSizeClass
和.verticalSizeClass
来检测设备的尺度类别
,并根据需要运用不同的布局和款式
struct ContentView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.verticalSizeClass) var verticalSizeClass
var body: some View {
VStack(alignment: .leading) {
if horizontalSizeClass == .compact && verticalSizeClass == .regular {
layoutWithUserInterfaceIdiom()
} else {
HStack {
layoutWithUserInterfaceIdiom()
}
}
}
}
}
UIDevice.current.userInterfaceIdiom
UIDevice.current.userInterfaceIdiom
是UIKit
中用于判断设备类型的特点,能够在iPhone
和iPad
之间进行适配,但如果需要在SwiftUI
中运用UIKit
特点来判断设备类型,也是能够的
struct ProfileHeaderView: View {
@State var userInterfaceIdiom = UIDevice.current.userInterfaceIdiom
var body: some View {
VStack(alignment: .leading) {
if userInterfaceIdiom == .phone {
HStack {
layoutWithUserInterfaceIdiom()
}
} else {
layoutWithUserInterfaceIdiom()
}
}
}
}
小结
关于SwiftUI
的学习,与UIkit
的学习路线大致上是类似的,但由于SwiftUI
是一种全新的声明式结构
,运用方法和一些概念可能会有所不同
关于SwiftUI 结构
的运用,本文首要叙述了其通用 UI控件
、款式
、动画
、生命周期
以及适配
问题等,在后续的文章中会陆续对SwiftUI
中的特点包装器
、缓存
以及网络请求
进行谈论及总结