【发布时间】:2019-06-25 21:32:23
【问题描述】:
大多数显示Alert 的示例指的是某种@State 被用作控制警报视图的呈现/隐藏状态的绑定。
以showingAlert(source)为例:
struct ContentView : View {
@State var showingAlert = false
var body: some View {
Button(action: {
self.showingAlert = true
}) {
Text("Show Alert")
}
.alert(isPresented: $showingAlert) {
Alert(
title: Text("Important message"),
message: Text("Wear sunscreen"),
dismissButton: .default(Text("Got it!"))
)
}
}
}
当从 UI 层触发警报时,这是一个很好的解决方案 - 如示例中所示:
Button(action: {
self.showingAlert = true
}
但是如果我们想从控制器/视图模型层用特定消息触发它呢? 例如,我们进行网络调用 - URLSession 的 Publisher 可以发送Data 或 Error,我们希望将其作为 Alert 中的消息推送给用户。
@State 被设计为从视图的body 进行管理,因此在这种情况下我们似乎应该使用@ObjectBinding。看来我们还需要一些message,所以可以在body中引用:
Alert(
title: Text("Important message"),
message: Text(objectBinding.message)
)
showingAlert 在这里有点多余,因为我们可以将message 定义为String? 并为presentation 创建一个绑定:
Binding<Bool>(
getValue: { objectBinding.message != nil },
setValue: { if !$0 { objectBinding.message = nil } }
)
这是一种可行的方法,而且很有效,但有两件事让我有点焦虑:
-
message由两个抽象管理这一事实 - 警报的显示/隐藏状态的信息和管理泄漏到控制器/视图模型/对象绑定中。最好将呈现/隐藏状态私下保留在视图中。
- 事实上,消息一直保存在控制器/视图模型/对象绑定中,直到它被视图(绑定)“消费”。
可以做得更好吗?
【问题讨论】:
-
真相的来源在哪里?尽管声明它由两个抽象管理,但需要有一个单一的来源。如果不是,那么您正在做的事情还有其他问题。 (范式转变?)
-
感谢您的评论@dfd。更具体的例子是将网络请求委托给
objectBinding。URLSession的Publisher(由objectBinding管理)可以发送Data或Error,因此objectBinding是错误消息的真实来源。我不确定将Alert的呈现/隐藏状态保留在那里是否是一个好习惯 -
是的 - 这绝对是一个范式转换问题。在命令式世界中,我只需订阅
Publisher,传递错误消息,触发警报并收工 - 呈现/隐藏状态将由视图本身管理,我不需要以某种方式缓存错误消息。
标签: ios swift swiftui ios13 combine