Swift 这个快捷界面如何绑定+;状态示例是否能够在不重新调用主体的情况下工作?

Swift 这个快捷界面如何绑定+;状态示例是否能够在不重新调用主体的情况下工作?,swift,swiftui,Swift,Swiftui,一位同事提出了下面的SwiftUI示例,它看起来就像预期的那样工作(您可以输入一些文本,它会在下面镜像),但它的工作方式令我惊讶 import SwiftUI struct ContentView: View { @State var text = "" var body: some View { VStack { TextField("Change the string", text: $text

一位同事提出了下面的SwiftUI示例,它看起来就像预期的那样工作(您可以输入一些文本,它会在下面镜像),但它的工作方式令我惊讶

import SwiftUI

struct ContentView: View {
    @State var text = ""
    var body: some View {
        VStack {
            TextField("Change the string", text: $text)
            WrappedText(text: $text)
        }
    }
}

struct WrappedText: View {
    @Binding var text: String
    var body: some View {
        Text(text)
    }
}
我的新手SwiftUI心智模型让我想到,在TextField中键入会改变
$text
绑定,这反过来会变异
text
@State变量。这将使
ContentView
无效,触发对
body
的新调用。但有趣的是,事实并非如此!在ContentView的
body
中设置断点只会命中一次,而WrappedText的
body
会在每次绑定更改时运行。然而,据我所知,
文本
状态确实在变化


那么,这是怎么回事?为什么SwiftUI不在每次更改
文本时重新调用ContentView的主体?

在状态更改时SwiftUI呈现引擎首先检查主体内的视图是否相等,如果其中一些视图不相等,则调用主体重新生成,但只调用那些不相等的视图。在您的情况下,没有一个视图(作为值)依赖于
text
value(绑定就像一个引用-它是相同的),因此在这个级别上不需要重建任何内容。但是在
WrappedText
内部,检测到带有新
Text
Text
与带有旧
Text
WrappedText
不相等,因此调用
WrappedText
的主体来重新渲染此部分

这是对SwiftUI的渲染优化-通过平等性检查和验证准确的更改视图

默认情况下,该机制通过视图结构属性工作,但我们可以通过将视图确认为
Eqatable
协议并将其标记为
.equatable()
修饰符来参与该机制,以提供一些更复杂的逻辑来检测视图是否应该(或不应该)重新渲染