如何解决这个SwiftUI绑定+状态示例如何在不重新调用主体的情况下工作?
一位同事提出了以下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
将被运行。然而,据我所知,text
的状态确实正在发生变化。
那么,这是怎么回事?为什么每次对text
进行更改时,SwiftUI都不会重新调用ContentView的正文?
解决方法
在状态更改上,SwiftUI渲染引擎首先检查主体内部视图的相等性,如果其中一些不相等,则调用主体进行重建,但仅调用那些不相等的视图。在您的情况下,没有一个视图(作为值)依赖于WrappedText
的值(绑定就像一个引用,它是相同的),因此在此级别上无需重建。但是在Text
内部检测到带有新text
的{{1}}不等于带有旧text
的{{1}},因此调用WrappedText
的正文重新渲染这部分。
这被宣布为SwiftUI的渲染优化-通过相等性检查和验证准确的更改视图。
默认情况下,此机制通过View的struct属性起作用,但是我们可以通过确认对Eqatable
协议的视图并将其标记为.equatable()
修饰符来参与其中,以提供一些更复杂的逻辑来检测View是否应该(或不应该)重新渲染。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。