如何在Swift模型的异步函数中等待View按钮点击?
在Swift模型异步函数中等待View按钮点击的实现方案
要让模型里的异步函数等待用户的弹窗点击决策,核心是利用Swift Concurrency的Continuation机制,挂起函数执行直到用户交互完成后恢复。以下是具体实现步骤:
1. 调整模型逻辑
在模型中添加用于挂起等待的方法、存储Continuation的变量,以及处理用户结果的逻辑:
class YourModel: ObservableObject { @Published var isShowingYesNoPopover = false private var decisionContinuation: CheckedContinuation<Bool, Never>? func doSomething() async { await firstFunction() // 触发弹窗显示 isShowingYesNoPopover = true // 挂起函数,等待用户决策 let shouldProceed = await waitForUserDecision() // 根据用户选择决定是否执行后续函数 if shouldProceed { await secondFunction() } // 隐藏弹窗 isShowingYesNoPopover = false } // 封装挂起逻辑的私有方法 private func waitForUserDecision() async -> Bool { await withCheckedContinuation { continuation in self.decisionContinuation = continuation } } // 接收用户点击结果,恢复挂起的函数 func yesNoRequesterResult(result: Bool) { decisionContinuation?.resume(returning: result) decisionContinuation = nil // 清空避免重复调用 } // 示例异步函数 func firstFunction() async {} func secondFunction() async {} }
2. 绑定View与弹窗
确保弹窗的显示状态绑定到模型的属性,保持逻辑统一:
struct YourView: View { @ObservedObject var model: YourModel var body: some View { // 主视图内容示例 Text("Main Content") .popover(isPresented: $model.isShowingYesNoPopover) { yesNoRequester } } var yesNoRequester: some View { VStack { Text("Do you like it?") HStack { Button(action: { model.yesNoRequesterResult(result: false) }, label: { Text("No") }) Button(action: { model.yesNoRequesterResult(result: true) }, label: { Text("Yes") }) } .padding() } } }
关键逻辑说明
decisionContinuation:用来暂存挂起的函数上下文,用户点击按钮后调用resume方法恢复函数执行,并传递决策结果。waitForUserDecision:通过withCheckedContinuation包装,让doSomething函数在此处挂起,直到用户做出选择。- 弹窗的显示/隐藏完全由模型控制,确保业务逻辑与视图展示解耦。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

