欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SwiftUI 简明教程之合理使用 EquatableView

程序员文章站 2022-06-22 10:10:47
本文为 Eul 样章,如果您喜欢,请移步 AppStore/Eul 查看更多内容。 Eul 是一款 SwiftUI & Combine 教程 App(iOS、macOS),以文章(文字、图片、代码)配合真机示例(Xcode 12+、iOS 14+,macOS 11+)的形式呈现给读者。笔者意在尽可能 ......

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 查看更多内容。