嵌套UIAlert问题:UIAlertAction中弹窗后逻辑重复触发
问题解决:UIAlertAction等待第二个弹窗操作完成
问题场景
在第一个UIAlertAction的处理逻辑中,调用deletePoints方法展示第二个UIAlertController时遇到两个问题:
- 第一个弹窗的Action不会等待第二个弹窗的操作完成,直接执行后续代码
- 第二个弹窗结束后,第一个Action的逻辑似乎被触发了两次
问题根源
原代码中deletePoints是同步调用,执行完弹窗展示后立刻回到第一个Action的handler继续执行后续的积分添加逻辑,完全没有等待用户对第二个弹窗的操作。同时,循环遍历selectedIndexPaths的逻辑可能因弹窗展示时机问题导致重复执行。
解决方案
通过**闭包(Completion Handler)**让deletePoints在用户完成第二个弹窗操作后,再回调第一个Action的handler执行后续逻辑:
步骤1:修改deletePoints方法,添加Completion闭包
func deletePoints(table: [Tables], completion: @escaping (Bool) -> Void) { let pointsAlertController = UIAlertController(title: "Some text", message: "Delete points?", preferredStyle: .alert) // 取消按钮:不删除积分,回调false pointsAlertController.addAction(UIAlertAction(title: "Nein", style: .cancel, handler: { _ in completion(false) })) // 确认按钮:删除积分,回调true pointsAlertController.addAction(UIAlertAction(title: "Ja", style: .default, handler: { [self] _ in table[0].points -= 100 self.tablesService?.update(updatedTable: table[0]) completion(true) })) self.present(pointsAlertController, animated: true) }
步骤2:修改第一个Action的handler逻辑,等待闭包回调
将原本直接执行的后续积分逻辑放到deletePoints的completion闭包中,确保只有用户操作完第二个弹窗后才执行:
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { [self] _ in for (index, indexPath) in selectedIndexPaths.enumerated() { // some code... if table[0].points >= 100 { // 调用deletePoints,等待用户操作完成后再执行后续逻辑 deletePoints(table: table) { [self] _ in // 这里放原本在deletePoints之后的代码 if position?.category == 0 { if table[0].segment == 3 { table[0].points += 5 self.tablesService?.update(updatedTable: table[0]) } } // some code... } } else { // 如果不需要弹窗,直接执行后续逻辑 if position?.category == 0 { if table[0].segment == 3 { table[0].points += 5 self.tablesService?.update(updatedTable: table[0]) } } // some code... } } }))
额外注意点
- 确保
selectedIndexPaths的遍历逻辑不会因弹窗重复触发,建议在第一个弹窗的Action执行时先禁用相关交互或标记状态,避免重复触发 - 闭包中注意捕获
self的循环引用问题,这里用[self]是安全的,因为UIAlertAction的handler会在执行后释放
内容的提问来源于stack exchange,提问作者Gökhan
相关产品推荐
相关产品推荐

