Как работать с привязками при использовании модели представления и использования @Binding в самом представлении? - PullRequest
0 голосов
/ 31 марта 2020

@State и @Binding так хорошо работают в SwiftUI, если вы помещаете все данные представления в себя, например:

struct ColorView: View {
    @Binding public var isBlue: Bool

    var body: some View {
        Rectangle()
            .foregroundColor(isBlue ? .blue : .red)
            .onTapGesture {
                self.isBlue.toggle()
        }
    }
}

struct TestView: View {
    @State var isBlue: Bool = false

    var body: some View {
        ColorView(isBlue: $isBlue)
    }
}

Это работает без проблем, и это действительно просто. Но MVVM говорит, что вы должны поместить все данные представления в класс модели представления, чтобы отделить пользовательский интерфейс от модели. Но тогда вы теряете @State и @Binding полностью. Вы теряете это двустороннее связывание, кажется. Конечно, вы можете сделать это вручную с помощью Combine или чего-то еще, но это не должно быть правильным способом, верно?

Всякий раз, когда я что-то пробую, SwiftUI действительно легко и удобно, когда вы не используете модели представлений. Как только вы помещаете все в класс модели представления, все разрушается, и больше ничего не работает. Этого не может быть, они должны были подумать об этом. Так что я что-то здесь упускаю. Буду очень признателен за любую помощь. Как бы вы кодировали приведенный выше пример, используя модели представления (без «взлома» чего-либо вручную)? Я пытался, но он даже не компилируется:

struct ColorView: View {
    @ObservedObject var viewModel: ViewModel

    class ViewModel: ObservableObject {
        // Binding or Published? Both doesn't seem to work
        @Binding var isBlue: Bool

        init(isBlue: Binding<Bool>) { // Or type Bool? But then we lose the binding
            self.$isBlue = isBlue
        }
    }

    var body: some View {
        Rectangle()
            .foregroundColor(viewModel.isBlue ? .blue : .red)
            .onTapGesture {
                self.viewModel.isBlue.toggle()
        }
    }
}

struct TestView: View {
    @ObservedObject var viewModel: ViewModel

    class ViewModel: ObservableObject {
        @Published var isBlue: Bool = false // We would need a @State here, but then we lose @Published
    }

    var body: some View {
        ColorView(viewModel: .init(isBlue: /* ??? */)) // How to pass a binding here`
    }
}

Думаю ли я об этом неправильно?

Спасибо!

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Использование MVVM - ваш выбор, Apple официально не рекомендует использовать какой-либо шаблон проектирования. Они дали нам концепции ниже, и это действительно зависит от нас, как мы можем их использовать.

1- Оболочки свойств (@State, @Binding, @Environment)

2- SwiftUI замена раскадровок

3 - Платформа Combine предоставляет декларативный Swift API для обработки значений во времени, таких как RxSwift, Rx Java, Rx Kotlin et c.

Если вы хотите используя MVVM, вы все равно будете использовать все вышеперечисленные фреймворки

View : разработка и привязка вида с помощью SwiftUI.

ViewModel : Здесь вы будете использовать свойства @Observable, @Published и связывать их с помощью View, используя концепции связывания SwiftUI.

Model : здесь мы используем простые модели данных.

Сеть : Здесь мы будем использовать механизм публикации / подписчика Framework для обработки сетевых потоков.

ПРИМЕЧАНИЕ. Можно объединить все вышеперечисленные концепции и использовать его в другом шаблоне проектирования, таком как MVP , MVC или VIPER.

1 голос
/ 31 марта 2020

Вот способ (при условии, что где-то вы звоните TestView(viewModel: ViewModel())):

class ViewModel: ObservableObject {
    @Published var isBlue: Bool = false
}

struct TestView: View {
    @ObservedObject var viewModel: ViewModel

    var body: some View {
        ColorView(viewModel: self.viewModel)
    }
}

struct ColorView: View {
    @ObservedObject var viewModel: ViewModel

    var body: some View {
        Rectangle()
            .foregroundColor(viewModel.isBlue ? .blue : .red)
            .onTapGesture {
                self.viewModel.isBlue.toggle()
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...