如何在 SwiftUI 视图之外触发绑定 SwiftUI.Alert 的呈现?

5

大多数显示Alert的示例都涉及使用某种@State作为绑定,以控制警报视图的显示/隐藏状态。

例如,showingAlert来源):

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
}
但是如果我们想从控制器/视图模型层使用特定的消息触发它怎么办? 例如,我们进行网络调用- URLSessionPublisher可以发送DataError,我们希望将其作为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 } }
)

这是一种可行的方法,它能够工作,但有两件事让我有些担忧:

  1. message 被两个抽象管理。
  2. 呈现/隐藏 警报状态的信息和管理泄漏到控制器 / 视图模型 / 对象绑定中。最好将 呈现/隐藏 状态私密地保留在视图中。
  3. 消息被保持在控制器 / 视图模型 / 对象绑定中,直到被视图 (绑定) "消耗" 掉。

有更好的方式吗?


真相在哪里?尽管它由两个抽象管理,但仍需要一个单一的来源。如果没有,那么你所做的事情就有其他问题了。(范式转变?) - user7014451
感谢您的评论@dfd。更具体的例子是将网络请求委托给objectBindingURLSessionPublisher(由objectBinding管理)可以发送DataError,因此objectBinding是错误消息的真实来源。我不确定在那里也保持Alert显示/隐藏状态是否是一个好习惯。 - Maciek Czarnik
是的 - 这绝对是一个范式转变问题。在命令式世界中,我只需订阅该“发布者”,传递错误消息,触发警报并结束 - “呈现/隐藏”状态将由视图本身管理,我不需要以某种方式缓存错误消息。 - Maciek Czarnik
1个回答

1
如果您特别想使用Combine及其发布者机制,您可以尝试使用onReceive()。每个通用的SwiftUI视图都有onReceive()作为接受发布者的通用函数,在实例化时将订阅该发布者。它的行为与您熟悉的单闭包版本的Combine订阅者sink非常相似。
发布者的细节要求此操作的发布者失败类型为Never,因此,如果您从某些管道中的Error进行操作,您需要将其转换为其他类型的对象(例如具有关联String值的Enum)并外部化它们,以便可以在SwiftUI中显示它们。
您最终如何将发布者公开到SwiftUI视图可能也很麻烦-我一直通过将发布者添加到具有其他@Published属性的引用对象上来执行此操作。

您可以在使用Combine中看到一个大致的示例,了解它是如何工作的(虽然不是您特定的用例),网址为https://heckj.github.io/swiftui-notes/#pattern-observableobject


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接