Передача BindableObject в представления - PullRequest
1 голос
/ 09 июня 2019

Из сессий Apple и Tutorial у нас есть две опции для передачи BindableObject представлениям.

  1. Используйте объявление сотню BindableObject как источник истины в виде сверху в иерархии с @ObjectBindingобернуть и передать его в другие представления с объявленным @Binding.
  2. Использовать объявить BindableObject в качестве источника истины в верхнем представлении в иерархии с оберткой @EnviromentObject, начальном представлении сверху с модификатором .enviroment(BindableObject)и передать его в другие представления либо с объявленным @Binding, либо с использованием @EnviromentObject (в этом случае SwiftUI будет автоматически назначать BindableObject, и нам не нужно передавать его при инициализации).

Из Обучающее руководство по пользовательскому вводу если у нас есть BindableObject со списком элементов и мы хотим изменить один из элементов в другом представлении (или RowView или даже отдельном экране), нам нужно:

  1. Передайте BindableObject в более глубокое представление любым из способов выше.
  2. Передача выбранного элемента в это представление.
  3. Свяжите свойство элемента с помощью BindingView, найдя элемент в списке BindableObject.

Некоторый код, чтобы прояснить вопрос:

Модель сообщения и BindableObject

struct Message: Identifiable {
    var id: String
    var toggle: Bool = true
}

class MessageStore: BindableObject {

  let didChange = PassthroughSubject<MessageStore, Never>()

  var messagesList: [Message] = testData {
    didSet {
      didChange.send(self)
    }
  }
}

MessageView, представляющий список элементов struct MessagesView

 : View {

    @EnvironmentObject var messageStore: MessageStore

    var body: some View {
        NavigationView {
            List(messageStore.messagesList) { message in
                NavigationButton(destination: Text(message.id)) {
                    MessageRow(message: message)
                }
            }
            .navigationBarTitle(Text("Messages"))
        }
    }
}

MessageRowкоторый имеет переключатель для обновления состояния определенного элемента в BindableObject

struct MessageRow: View {

    @EnvironmentObject var tags: MessageStore
    var message: Message

    var messageIndex: Int {
        tags.messagesList.firstIndex { $0.id == message.id }!
    }


    var body: some View {
       Toggle(isOn: self.$tags.messagesList[self.messageIndex].toggle) {
           Text("Test toogle")
       }
    }

}

Этот подход показан в учебнике, о котором я упоминал выше.

Вопрос: Я хотел передать Message отдельно как @Binding, чтобы напрямую работать с ним в дочернем представлении, но я не смог реализовать это.Я немного запутался.Является ли правильным способом перейти к любому представлению (которое должно обрабатывать привязки) как BindableObject, так и выбранному элементу для последующей привязки элемента из BindableObject с использованием индекса?Есть ли другой способ, который позволит пройти не полную BindableObject, а ее часть и связать эту часть (это должен быть Источник истины), в нашем случае эта часть Message?

1 Ответ

0 голосов
/ 09 июня 2019

Я думаю, вы слишком усложняете это.Кажется, все, что вам нужно, это значение переключателя в вашем сообщении.Попробуйте это:

var body: some View {
    NavigationView {
        List(messageStore.messagesList) { message in
            NavigationButton(destination: Text(message.id)) {
                MessageRow(isTogged: $message.toggle)
            }
        }
        .navigationBarTitle(Text("Messages"))
    }
}

struct MessageRow: View {

    @Binding var isToggled: Bool

    var body: some View {
        Toggle(isOn: self.isToggled) {
            Text("Test toogle")
        }
    }
}
...