简体   繁体   English

SwiftUI-ObservableObject重绘不相关的视图?

[英]SwiftUI - ObservableObject redraws unrelated views?

When a @Published property is mutated in an ObservableObject , SwiftUI seems to re-draw views which do not depend on that property. @Published属性在ObservableObject发生突变时,SwiftUI似乎会重新绘制不依赖于该属性的视图。

Example

You can see the behavior here: 您可以在此处查看行为:

// Our observed model
class Person: ObservableObject {
    @Published var name = "Bob"
    @Published var title = "Mr"
    static let shared = Person()
    init() {}
}


// Name view
struct NameView: View {
    @ObservedObject var person = Person.shared
    var body: some View {
        print("Redraw name")
        return TextField("Name", text: $person.name) // Binding to `name` only
    }
}

/* Elsewhere in the app... */
// Title view
struct TitleView: View {
    @ObservedObject var person = Person.shared
    var body: some View {
        print("Redraw title")
        return TextField("Title", text: $person.title) // Binding to `title` only
    }
}

Build an app containing both views, and change either the name OR the title. 构建一个包含两个视图的应用,然后更改名称或标题。 For each character typed, you'll see this console output: 对于每个键入的字符,您将看到以下控制台输出:

Redraw name
Redraw title

Question

Why does TitleView 's body get re-computed when you modify name , and vice versa? 为什么在修改name时会重新计算TitleView的主体,反之亦然?

This has become a huge problem in my app: a shared User object (via @EnvironmentObject) is triggering drawing cycles in completely unrelated views. 这在我的应用程序中已成为一个巨大的问题:共享的User对象(通过@EnvironmentObject)正在触发完全不相关的视图中的绘制周期。 Modifying the User 's name in one view causes another view to re-render a long list of photos owned by the same User (expensive operation). 在一个视图中修改User名会导致另一个视图重新渲染由同一User拥有的一长串照片(昂贵的操作)。 What's worse - this happens with every keystroke typed . 更糟糕的是,每次键入击键都会发生这种情况。

Is SwiftUI smart enough to selectively redraw only views that display the mutated @Published property? SwiftUI是否足够聪明,可以有选择地重绘显示突变的@Published属性的视图?

Under the hood @ObservedObject uses a Combine Subscriber to observe your ObservableObject . @ObservedObject使用组合Subscriber观察ObservableObject

Consider this refactor of your Person object: 考虑您的Person对象的以下重构:

class Person: ObservableObject {

    var name = "My name" {
        willSet { self.objectWillChange.send() }
    }
    var title = "My title" {
        willSet { self.objectWillChange.send() }
    }

    static let shared = Person()

    init() {}

}

As you can see the Person object "owns" a Publisher assigned to objectWillChange . 如您所见, Person对象“拥有”一个分配给objectWillChangePublisher objectWillChange And all @Property is doing is removing some boilerplate from your object model by handling willSet for you. @Property所做的只是通过为您处理willSet从对象模型中删除一些样板。

So ObservableObject itself is not granular enough to detect a change to a particular property in your model but rather is "broadcasting" a change for any property change in your model and @ObservedObject is simply subscribed to any change to your model. 因此, ObservableObject本身的粒度不足以检测模型中特定属性的更改,而是“广播”模型中任何属性更改的更改,而@ObservedObject只是订阅了模型中的任何更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM