【发布时间】:2019-10-24 04:20:36
【问题描述】:
从 Apple 的会话和教程中,我们有两个选项可以将 BindableObject 传递给视图。
- 使用声明
BindableObject作为具有@ObjectBinding包装器的层次结构顶部视图中的事实来源,并将其传递给声明@Binding的其他视图。 - 使用声明
BindableObject作为层次结构顶部视图中的事实来源,使用@EnviromentObject包装器,使用.enviroment(BindableObject)修饰符初始化顶部视图并将其传递给其他视图或声明@Binding,或使用@ 987654329@(在这种情况下,BindableObject将由 SwiftUI 自动分配,我们不需要在 init 时传递它)。
来自Handling User Input tutorial,如果我们有带有项目列表的BindableObject,并且我们想要更改其他视图(或RowView甚至单独屏幕)上的项目之一,我们需要:
- 使用上述任何一种方式将
BindableObject传递到更深层的视图。- 将所选项目传递到此视图。
- 通过在
BindableObject列表中查找项目,将项目的属性与BindingView绑定。
一些代码让问题更清楚:
消息模型和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 结构消息视图
: 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 有一个 Toggle 来更新特定项目的状态 in out 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?
【问题讨论】:
-
感谢您发布此信息。我刚刚遇到了同样的问题,并且遇到了完全相同的令人困惑的问题。 Apple 自己的教程似乎支持了一种做法,坦率地说,我认为他们应该为此感到尴尬。他们新的旗舰 UI 系统似乎只适合简单的 UI;无法直接传递绑定的子对象是一个有趣的限制,因此强制对其进行详尽的搜索或将索引传递给它。史蒂夫乔布斯在他的坟墓里旋转。