更新属性包装器(如 @StateObject)会影响不使用该属性的其他视图渲染

2024-04-14

当使用与视图更新关联的不同属性包装器时,一处的更改会影响不使用该属性的视图的呈现。

struct ContentView: View {

    @StateObject var viewModel = MyViewModel()
    @State var thirdTitle = "thirdTitle"

    var body: some View {
        VStack {
            Text(viewModel.firstTitle)
                .background(.random)
            Text(viewModel.secondTitle)
                .background(.random)
            Text(thirdTitle)
                .background(.random)

            Button("Change First Title") {
                viewModel.chageFirstTitle()
            }
        }
    }
}

class MyViewModel: ObservableObject {
    
    @Published var firstTitle = "firstTitle"
    @Published var secondTitle = "secondTitle"
    
    func chageFirstTitle() {
        firstTitle = "hello world"
    }
}

我明白为什么Text暴露viewModel.secondTitle被重新渲染是因为@StateObject varviewModel = MyViewModel()当“viewModel.firstTitle”更改时,依赖项也会更改。

然而我不知道为什么Text using @State var thirdTitle = "thirdTitle"也被重新渲染。在 WWDC21 会议中揭秘 SwiftUI https://developer.apple.com/videos/play/wwdc2021/10022/?time=390,我看到只有根据依赖关系图更新相关依赖关系时,视图才会重新渲染。但是,尽管thirdTitle与改变无关viewModel, third Text使用该依赖项将重新渲染并更改背景颜色。

更令人困惑的是,如果我将第三个分开Text进入单独的视图(ThirdView)并收到thirdTitle using @Binding,背景颜色不会改变,因为当时没有重新渲染。

struct ContentView: View {

    @StateObject var viewModel = MyViewModel()
    @State var thirdTitle = "thirdTitle"

    var body: some View {
        VStack {
            Text(viewModel.firstTitle)
                .background(.random)
            Text(viewModel.secondTitle)
                .background(.random)
            ThirdView(text: $thirdTitle)
                .background(.random)

            Button("Change First Title") {
                viewModel.chageFirstTitle()
            }
        }
    }
}

struct ThirdView: View {
    
    @Binding var text: String
    
    var body: some View {
        Text(text)
            .background(.random)
    }
}

关于我解释的情况,你能帮我了解一下视图的渲染条件吗?


渲染 SwiftUI 调用body视图的属性(它是可计算的,即完全在调用时执行)。每当任何视图依赖项(即动态属性)发生更改时都会执行此调用。

So, viewModel.chageFirstTitle()更改依赖关系ContentView and ContentView.body被调用并且其中的每个基元都被渲染。ThirdView也创建了,但只要它的依赖关系没有改变,它的body没有被调用,所以内容不会被重新渲染。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更新属性包装器(如 @StateObject)会影响不使用该属性的其他视图渲染 的相关文章

随机推荐