SwiftUI 中的异步警报

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

我试图在 asnyc 抛出函数错误时弹出警报,但它似乎不起作用。 以下是视图中元素的简化版本: 我在视图顶部声明:

@State private var onError: Bool = false

然后按钮调用异步函数:

Button {
    Task {
        await wait()
    }
} label: {
    Text("Button")
}
.alert(isPresented: $onError) {
    Alert(title: Text("An Error has occured!"), dismissButton: .cancel())
}

它本身调用异步抛出函数:

private func wait() async {
    do {
        try await someAsyncThrowingFunc()
    } catch {
        print(error)
        // onError = true
        DispatchQueue.main.async{
            onError = true
        }
    }
}

出现错误时,会打印错误消息,但不会弹出警报。

我也尝试过直接向按钮抛出错误

private func wait() async throws {
    do {
        try await someAsyncThrowingFunc()
    } catch {
        print(error)
        throw error
    }
}

或者甚至将 Bool 返回给按钮

private func wait() async -> Bool {
    do {
        try await someAsyncThrowingFunc()
    } catch {
        print(error)
        return true
    }
    return false
}

但是没关系,弹出窗口永远不会显示。

我真的不知道还能做什么才能让它发挥作用;所以提前感谢您的帮助。

swift swiftui alert
2个回答
0
投票

它是

.task
不是
Task
并且您不能使用
DispatchQueue
,因为
View
是结构值类型而不是类引用类型,请尝试一下:

Button {
    running.toggle()
} label: {
    Text(running ? "Stop" : "Start")
}
.task(id: running) {
   if !running {
      return
   }
   await wait()
   running = false
}
.alert(isPresented: $onError) { [onError] in
    Alert(title: Text("An Error has occured!"), dismissButton: .cancel())
}
...
private func wait() async {
    do {
        results = try await someAsyncThrowingFunc()
    } catch {
        print(error) // cancel error if Button is toggled while running
        onError = true
    }
}

0
投票

好吧,我的错,我想问题实际上来自于这个视图嵌入到另一个视图中这一事实。正如另一个(thread)中提到的,一个简单的修复是:

public struct EmbededView: View {
    @Binding var showAlert: Bool
    @Binding var alert: Alert?
    public init(showAlert:  Binding<Bool>, alert: Binding<Alert?>) {
        self._showAlert = showAlert
        self._alert = alert
    }
    
    public var body: some View {
        ...
        Button {
            Task {
                await wait()
            }
        } label: {
            Text("Try")
        }
        ...
    }
    
    private func wait() async {
        do {
            try await someAsyncThrowingFunc()
        } catch {
            print(error)
            alert = Alert(title: Text("An Error has occured!"), dismissButton: .cancel())
            self.showAlert.toggle()
        }
    }
}
public struct TopLevelView: View {
    @State private var showAlert = false
    @State private var alert: Alert? = nil
    
    public var body: some View {
        ScrollView {
            ...
            EmbededView(howAlert: $showAlert, alert: $alert)
            ...
        }
        .alert(isPresented: $showAlert) {
            alert!
        }
    }
}

感谢您的帮助,如果有人遇到同样的问题,希望此解决方案可以有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.