在视图外触发时如何绑定 SwiftUI.Alert 的呈现?
Posted
技术标签:
【中文标题】在视图外触发时如何绑定 SwiftUI.Alert 的呈现?【英文标题】:How to bind presentation of SwiftUI.Alert when triggered outside of the View? 【发布时间】: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
,传递错误消息,触发警报并收工 - 呈现/隐藏状态将由视图本身管理,我不需要以某种方式缓存错误消息。
【参考方案1】:
如果您特别想使用 Combine 及其发布者机制,您可以使用 onReceive()
。每个通用 SwiftUI 视图上都有 onReceive()
作为接受发布者的通用函数,并且在实例化时将订阅发布者。如果您熟悉的话,它的行为与 Combine 订阅者 sink
的单闭包版本非常相似。
发布者的细节期望发布者的失败类型为 Never 才能正常工作,因此如果您在某个管道中使用错误,则需要将它们转换为其他类型的对象(可能是 @987654328 @ 与关联的 String
值)并将它们外部化,以便它们可以使用 SwiftUI 显示。
你最终如何将发布者暴露给 SwiftUI 视图可能也很尴尬 - 我一直在通过将发布者添加到具有其他 @Published
属性的引用对象上来做到这一点。
您可以在Using Combinehttps://heckj.github.io/swiftui-notes/#pattern-observableobject 中查看其工作原理的粗略示例(尽管不是您的特定用例)
【讨论】:
以上是关于在视图外触发时如何绑定 SwiftUI.Alert 的呈现?的主要内容,如果未能解决你的问题,请参考以下文章
iOS:如何在其附件视图更改时触发 tableViewCell 的约束/自动布局刷新?
Stickit:如何在每个模型后触发更改事件 -> 视图更改