SwiftUI 简明教程之合理使用 EquatableView
Posted Bruce2077
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SwiftUI 简明教程之合理使用 EquatableView相关的知识,希望对你有一定的参考价值。
本文为 Eul 样章,如果您喜欢,请移步 AppStore/Eul 查看更多内容。
Eul 是一款 SwiftUI & Combine 教程 App(ios、macOS),以文章(文字、图片、代码)配合真机示例(Xcode 12+、iOS 14+,macOS 11+)的形式呈现给读者。笔者意在尽可能使用简洁明了的语言阐述 SwiftUI & Combine 相关的知识,使读者能快速掌握并在 iOS 开发中实践。
EquatableView 使用
在实际开发中,很多界面可能是不需要频繁刷新的。虽然 SwiftUI 中的视图非常廉价,但是,如果有一种方法能减少只有在特定条件下需要刷新的视图的重绘,那么何乐而不为呢?而 EquatableView 可以做到这一点,使视图树减少不必要的重绘,优化了性能。
我们先看看下面的例子:
enum WeatherState: String {
case sun = "sun"
case rain = "rain"
}
struct ContentView: View {
@State private var weatherState: WeatherState = .sun
var body: some View {
VStack {
Button {
weatherState = Bool.random() ? .sun : .rain
} label: {
Text("Random Weather")
}
.buttonStyle(BorderlessButtonStyle())
Text(weatherState.rawValue)
// 两种写法都可以
// EquatableView(content: WeatherView(weatherState: weatherState))
WeatherView(weatherState: $weatherState).equatable()
}
}
}
struct WeatherView: View, Equatable {
let weatherState: WeatherState
var body: some View {
print("刷新了: \\(weatherState.rawValue)")
return Text("WeatherView: \\(weatherState.rawValue)")
}
}
WeatherView 遵循了 Equatable 协议,目前我们并没有实现具体的协议方法。在使用 EquatableView 时,上面注释处的两种写法都是可以的。
试试运行代码,观察控制台,我们发现,只有天气发生变化的时候,WeatherView 才会去更新视图。
WeatherView 中的 weatherState
属于基础数据类型,对于这种简单的情况,只要视图遵循了 Equatable 协议,SwiftUI 会自动去比对其中的基础数据类型,如果值没有发生变化,就不会去刷新视图。
我们对代码做如下修改:
let weatherState: WeatherState
// 修改为:
@Binding var weatherState: WeatherState
这时候的 weatherState 就不属于基础数据类型了, 它是复杂数据类型。编译器会报错,提示“Type \'WeatherView\' does not conform to protocol \'Equatable\'”,因为 SwiftUI 无法处理这种复杂的情况,我们需要自己手动实现 Equatable 协议:
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.weatherState == rhs.weatherState
}
然后运行代码,效果与上面是一样的,只有天气变化时,视图才会刷新。
使用场景与注意
EquatableView 用于不需要频繁刷新界面的场景,或者视图只有特定的触发条件才需要刷新时,使用它是有益的。
值得注意的是,EquatableView 如果没有触发刷新机制,那么,视图中的属性也是不会更新的。比如,WeatherView 的属性是一个如下结构体:
struct WeatherData {
var weatherState: WeatherState
var temperature: CGFloat
}
而我们实现 Equatable 协议方法如下:
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.wetherData.weatherState == rhs.wetherData.weatherState
}
结果是只有天气状态 weatherState 变化时,才会刷新视图,而气温 temperature 的变化不会及时反映在视图上,这就造成了数据的错乱,这是值得注意的地方。
本文为 Eul 样章,如果您喜欢,请移步 AppStore/Eul 查看更多内容。
以上是关于SwiftUI 简明教程之合理使用 EquatableView的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 简明教程之 Swift Package Manager 的使用
SwiftUI 简明教程之OutlineGroupDiclosureGroupView