首页 > 解决方案 > 为什么@EnvironmentObject 强制重新初始化视图?

问题描述

在此示例中,当我在屏幕上拖动时,为什么会LabelViewRepresentable在每次“updateUIView”调用之前重新初始化?如果我将计数器设为@State属性而不是@EnvironmentObject属性,它只会像我期望的那样初始化一次。

import SwiftUI

class Counter: ObservableObject {
  @Published var count = 0
}

struct CounterView: View {
  @EnvironmentObject var counter: Counter

  var body: some View {
    LabelViewRepresentable(count: $counter.count)
      .gesture(DragGesture().onChanged({ _ in
        self.counter.count += 1
      }))
  }
}

struct LabelViewRepresentable: UIViewRepresentable {
  @Binding var count: Int
  private var view: UILabel

  init(count: Binding<Int>) {
    print("init")

    let label = UILabel()
    label.text = "0"
    self.view = label
    self._count = count
  }

  func makeUIView(context: UIViewRepresentableContext<LabelViewRepresentable>) -> UILabel {
    print("makeUIView")
    return view
  }

  func updateUIView(_ uiView: UILabel, context: UIViewRepresentableContext<LabelViewRepresentable>) {
    print("updateUIView")
    view.text = "\(count)"
  }
}

标签: iosswiftxcodeswiftui

解决方案


当您查看有关 EnvironmentObject 的 Apple 文档时,您会发现:

一个动态视图属性,它使用由祖先视图提供的可绑定对象,以在可绑定对象更改时使当前视图无效。

这意味着每次 EnvironmentObject 更改依赖于它的所有视图都会重新初始化和重绘。

它与 State 的工作方式略有不同,在 Apple 文档中描述如下:

给定类型的持久值,视图通过它读取和监视该值。

当状态更改时,视图无法重新初始化,因为状态值将被丢弃。受状态影响的部分将被重绘。另一方面,将 State 值作为绑定传入的视图的任何子视图都将被重新初始化。


推荐阅读