SwiftUI: @ObservedObject redr aws каждый просмотр - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь правильно реализовать MVVM в SwiftUI, поэтому я придумал эту (упрощенную) модель и ViewModel:

struct Model {
    var property1: String
    var property2: String
}

class ViewModel: ObservableObject {

    @Published var model = Model(property1: "this is", property2: "a test")

}

Использование этого в View работает нормально, но я испытал некоторые из-за проблем с производительностью, поскольку я расширил ViewModel некоторыми вычисленными свойствами и некоторыми функциями (а сам Model более сложен). Но давайте остановимся на этом примере, потому что он отлично демонстрирует, что я считаю большой проблемой в самом SwiftUI.

Представьте, у вас есть эти представления для отображения данных:

struct ParentView: View {

    @ObservedObject var viewModel: ViewModel

    var body: some View {
        print("redrawing ParentView")
        return ChildView(viewModel: self.viewModel)
    }
}

struct ChildView: View {

    @ObservedObject var viewModel: ViewModel

    var body: some View {
        print("redrawing ChildView")
        return VStack {
            ViewForTextField(property: self.$viewModel.model.property1)
            ViewForTextField(property: self.$viewModel.model.property2)
        }
    }

}

struct ViewForTextField: View {

    @Binding var property: String

    var body: some View {
        print("redrawing textView of \(self.property)")
        return TextField("...", text: self.$property)
            .textFieldStyle(RoundedBorderTextFieldStyle())
    }

}

Теперь ввод текста в один из TextField приводит к перерисовке каждые View в моем окне! Вывод на печать:

redrawing ParentView
redrawing ChildView
redrawing textView of this is
redrawing textView of a test
redrawing ParentView
redrawing ChildView
redrawing textView of this isa
redrawing textView of a test
redrawing ParentView
redrawing ChildView
redrawing textView of this isab
redrawing textView of a test
...

Как я вижу, SwiftUI redr aws каждый вид, потому что каждый вид слушает ObservedObject.

Как я могу сказать SwiftUI, что он должен перерисовывать только те представления, где действительно произошли какие-либо изменения?

Ответы [ 2 ]

0 голосов
/ 09 мая 2020

Если все ваши виды видят одну и ту же вещь, и эта вещь меняется, тогда все ваши взгляды будут перерисованы. Это по определению. Там нет никакой опции, чтобы настроить для необязательного обновления определенных представлений.

При этом вы можете обойти это, манипулируя, какие изменения вы хотели бы опубликовать sh.

Например;

class ViewModel: ObservableObject {

    @Published var model = Model(property1: "this is", property2: "a test")
    var mytext = "some text" // pass this as binding instead of model.propertyX
}

Теперь, когда изменяется текстовое поле, mytext изменяется, но это изменение не будет опубликовано, поэтому не будет запускать дальнейшие обновления просмотра. И вы по-прежнему можете получить к нему доступ из модели представления.

Я лично рекомендовал бы использовать @ State и @ EnvironmentObject вместо "модель представления". Они являются встроенным способом обработки привязок и просмотра обновлений с помощью множества средств защиты и поддержки.

Также вы должны максимально использовать тип значения вместо ссылочного типа. MVVM из других языков не принял это во внимание.

0 голосов
/ 28 апреля 2020

На самом деле MVVM означает собственную модель для каждого вида, которая обновляется при изменениях модели, а не одну модель для всех видов.

Таким образом, нет необходимости наблюдать viewModel в ParentView, поскольку это не зависит от него

struct ParentView: View {

    var viewModel: ViewModel // << just member to pass down in child

    var body: some View {
        print("redrawing ParentView")
        return ChildView(viewModel: self.viewModel)
    }
}

Альтернативой является декомпозиция модели представления, чтобы каждое представление имело собственную подмодель представления, которая будет управлять обновлениями собственного представления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...