能否为UIAlertController添加长按事件?含操作表及弹窗触发需求
这个需求挺实用的!不过UIAlertController本身并没有提供直接添加长按事件的官方API,我们得通过遍历它的子视图找到对应的交互元素,再给这些元素添加上长按手势来实现。下面分两种场景给你具体的实现方案,结合你提供的代码片段来调整:
一、ActionSheet模式下给选项添加长按事件
你现在的代码是循环给ActionSheet添加村庄名称的选项,我们需要在ActionSheet展示完成后,找到每个选项对应的按钮,再给它们绑定长按事件。
修改后的完整代码:
let actionSheet = UIAlertController(title: "Favourites", message: nil, preferredStyle: .actionSheet) if !favLocations.isEmpty { for i in 0..<favLocations.count { actionSheet.addAction(UIAlertAction(title: favLocations[i].villageName, style: .default, handler: { (action) in self.tbLocation.text = self.favLocations[i].villageName // 保留你原来的点击逻辑 })) } } // 记得添加取消按钮 actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) // 弹窗展示完成后,给选项按钮添加长按手势 present(actionSheet, animated: true) { self.addLongPressToActionSheetButtons(alert: actionSheet) } // 工具方法:遍历子视图找到所有选项按钮 func addLongPressToActionSheetButtons(alert: UIAlertController) { func findButtons(in view: UIView) -> [UIButton] { var buttons = [UIButton]() for subview in view.subviews { if let button = subview as? UIButton { // 过滤掉取消按钮(如果不需要给取消按钮加长按,可以保留这行) if button.titleLabel?.text == "Cancel" { continue } buttons.append(button) } buttons.append(contentsOf: findButtons(in: subview)) } return buttons } let buttons = findButtons(in: alert.view) for (index, button) in buttons.enumerated() { let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleActionSheetButtonLongPress(_:))) // 给手势绑定索引,方便对应到favLocations里的数据 longPress.setValue(index, forKey: "buttonIndex") button.addGestureRecognizer(longPress) } } // 长按事件的处理逻辑 @objc func handleActionSheetButtonLongPress(_ gesture: UILongPressGestureRecognizer) { // 只在长按开始时触发一次 guard gesture.state == .began else { return } guard let index = gesture.value(forKey: "buttonIndex") as? Int, index < favLocations.count else { return } let selectedVillage = favLocations[index] // 这里写你的长按逻辑,比如弹出删除确认弹窗、编辑地址等 print("长按了村庄:\(selectedVillage.villageName)") }
注意事项:
这种方式依赖于UIAlertController的内部视图结构,目前iOS 17及以下版本都是稳定可用的,但如果未来苹果修改了内部布局,可能需要调整遍历逻辑。
二、普通Alert弹窗模式下,长按后弹出另一个弹窗
如果是普通弹窗,你可以给整个弹窗视图添加长按手势,或者只给标题/消息区域添加,下面分别给出实现:
1. 给整个弹窗添加长按
// 创建普通弹窗 let mainAlert = UIAlertController(title: "主弹窗", message: "长按这个弹窗试试", preferredStyle: .alert) mainAlert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil)) // 添加长按手势到弹窗视图 let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleMainAlertLongPress(_:))) mainAlert.view.addGestureRecognizer(longPress) present(mainAlert, animated: true) // 长按触发后弹出第二个弹窗 @objc func handleMainAlertLongPress(_ gesture: UILongPressGestureRecognizer) { guard gesture.state == .began else { return } let secondAlert = UIAlertController(title: "长按触发", message: "你成功长按了主弹窗!", preferredStyle: .alert) secondAlert.addAction(UIAlertAction(title: "关闭", style: .default, handler: nil)) present(secondAlert, animated: true) }
2. 只给标题/消息区域添加长按
如果不想让按钮区域触发长按,可以找到弹窗里的UILabel,开启交互后添加手势:
// 在present弹窗之后调用这个方法 func addLongPressToAlertLabels(alert: UIAlertController) { func findLabels(in view: UIView) -> [UILabel] { var labels = [UILabel]() for subview in view.subviews { if let label = subview as? UILabel { labels.append(label) } labels.append(contentsOf: findLabels(in: subview)) } return labels } let labels = findLabels(in: alert.view) for label in labels { label.isUserInteractionEnabled = true // 开启交互,默认UILabel是关闭的 let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleMainAlertLongPress(_:))) label.addGestureRecognizer(longPress) } } // 调用方式:在present的completion里执行 present(mainAlert, animated: true) { self.addLongPressToAlertLabels(alert: mainAlert) }
内容的提问来源于stack exchange,提问作者siva kumar
相关产品推荐
相关产品推荐

