【问题标题】:How do I present an alert from a custom class in swiftui?如何在 swiftui 中显示来自自定义类的警报?
【发布时间】:2020-09-28 04:19:30
【问题描述】:

在 SwiftUI 中,我有一个网络请求在 scenedelegate 中运行,scenedidbecomeactive。我不知道当应用程序处于活动状态时用户将使用哪个视图,但我想在网络请求中的数据发生变化时发出警报。我简化了下面的代码,所以很容易阅读...

 func sceneDidBecomeActive(_ scene: UIScene) {
            let customClass = CustomClass()
            customClass.performNetworkRequest()

在 CustomClass 中,我有...

func performNetWorkRequest() {
URLSession.shared.dataTask(with: url) { (data, response, error) in          
      if let d = data {
         let response = try JSONDecoder().decode(DetailResponse.self, from: d)
             DispatchQueue.main.async {
                 //Here is where I want to either present an alert, but I can't figure out how to.
                 //OR do i put a func in SceneDeletegate to present the alert on the window.rootviewcontroller and then just call that func from here?
}

非常感谢任何帮助!

【问题讨论】:

  • 理想情况下,您的网络请求类会呈现任何内容。它只会更新一些环境观察对象,相关视图会做出反应。
  • 但我不确定用户在哪个视图上,因为它是scenedidbecomeactive,所以我必须将观察到的对象放入每个视图中吗?这似乎不太可扩展。我想我现在可以做到,因为只有 4-5 个视图。好的,让我试试看。
  • 我可能会将它放在带有 zstack 的根视图中,该 zstack 显示“toast”视图和您的正常视图。当有更新时,您可以在显示的其他内容之上显示吐司几秒钟。这听起来不像是您想要打断用户正在执行的操作以实际显示警报的情况,但您可以这样做。

标签: ios swift xcode swiftui uialertcontroller


【解决方案1】:

Paul 有一个观点 - 这是一个可能的实现:

// In CustomClass.swift

import Combine

class CustomClass : ObservableObject {

    @Published var dataRecieved = PassthroughSubject<DetailResponse, Never>()

    init() {
        performNetWorkRequest()
    }

    func performNetWorkRequest() {
        URLSession.shared.dataTask(with: url) { (data, response, error) in

            let response = try JSONDecoder().decode(DetailResponse.self, from: data)

            DispatchQueue.main.async {
                self.dataRecieved.send(response)
            }
        }
        .resume()
    }
}

// In SomeView.swift

import SwiftUI
import Combine

struct ContentView: View {

    @State var showAlert = false
    var customClass = CustomClass()

    var body: some View {
        Text("Hello, World!")
            .onReceive(customClass.dataRecieved) { _ in
                self.showAlert = true
            }
            .alert(isPresented: $showAlert) {
            // your alert
            }
    }
}

请注意,我没有在其中任何一个中提到 SceneDelegate - 在我看来,这种方法(称为 MVVM)更灵活 - 此外,它的设置方式,performNetWorkRequest() 将尽快执行无论如何,您的视图已初始化。 您还可以调整PassthroughSubject - 我不知道您是否需要DetailResponse。 希望这有帮助!

编辑:

我刚刚重读了您的问题,但您指出,在网络发生变化的情况下,无法知道用户将使用什么视图,因此该实现似乎有问题。在这种情况下,您可以在SceneDelegate 中将CustomClass 的相同实例作为EnvironmentObject 提供。

【讨论】:

  • 谢谢。是的,我想我必须这样做,然后将观察到的对象添加到用户可能在的每个视图中。
  • 工作就像一个魅力!
  • 如果所有视图都是单个视图的后代(例如 NavigationView 或 TabView),那么您可以只让那个视图呈现警报,并且无论哪个后代视图位于最顶层,都会看到它。但是,如果正在呈现 fullScreenCover 或 Sheet,并且您希望警报出现在它上面怎么办?在这种情况下,根视图的尝试将失败。如果有一种方法可以对屏幕上的任何内容发出警报,那就太好了。有什么想法吗,@akim?
猜你喜欢
  • 1970-01-01
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多