如何从 ContentView 外部显示 SwiftUI 警报?

问题描述 投票:0回答:2

我正在构建 Swift 应用程序,并试图找出如何显示警报。我有一个单独的 swift 文件正在执行一些计算,并且在某些条件下我希望它向用户显示警报,基本上告诉他们出了问题。但是,我看到的大多数示例都要求警报位于

ContentView
内或以其他方式连接到视图,并且我无法弄清楚如何从任何视图之外的单独文件显示警报。

我见过的大多数例子都是这样的:

struct ContentView: View {
@State private var showingAlert = false

var body: some View {
    Button("Show Alert") {
        showingAlert = true
    }
    .alert("Important message", isPresented: $showingAlert) {
        Button("OK", role: .cancel) { }
    }
}}
ios swift xcode swiftui alert
2个回答
5
投票

如果我正确理解你的问题,当计算中发生某些情况时,你希望在用户界面上显示

alert
。 计算发生在代码中的其他位置,例如监视传感器的任务。

这里我提出一种方法,使用

NotificationCenter
,如示例代码所示。无论何时何地,只要您在代码中,发送
NotificationCenter.default.post...
(如示例代码所示),警报就会弹出。

class SomeClass {
    static let showAlertMsg = Notification.Name("ALERT_MSG")
    
    init() {
        doCalculations() // simulate showing the alert in 2 secs
    }
    
    func doCalculations() {
        //.... do calculations
        // then send a message to show the alert in the Views "listening" for it
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            NotificationCenter.default.post(name: SomeClass.showAlertMsg, object: nil)
        }
    }
}

struct ContentView: View {
    let calc = SomeClass() // for testing, does not have to be in this View
    @State private var showingAlert = false
    
    var body: some View {
        Text("calculating...")
            .alert("Important message", isPresented: $showingAlert) {
                Button("OK", role: .cancel) { }
            }
            // when receiving the msg from "outside"
            .onReceive(NotificationCenter.default.publisher(for: SomeClass.showAlertMsg)) { msg in
                self.showingAlert = true // simply change the state of the View
            }
    }
}

0
投票

还有另一种解决方案。我们可以只发送一个参数作为@ObservedObject。

public class Parameter: ObservableObject {
    @Published public var cardNo: String
    
    public init(cardNo: String) {
        self.cardNo = cardNo
    }
}

struct CardView: View {
    @ObservedObject var parameter: Parameter
    
    var body: some View {
        Text("The card No: " + parameter.cardNo)
            .onReceive(parameter.$cardNo) { _ in
                // do what you want
            }
    }
}

// so here create init the cardView, 
var parameter: Parameter = .init(cardNo: "x1234")
CardView(parameter: parameter)

// and also we can change the cardNo outside from other thread
parameter.cardNo = "x3456"
© www.soinside.com 2019 - 2024. All rights reserved.