You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS17 TipKit(UIKit):点击提示Popover外部关闭的检测问题

解决UIKit中TipKit提示Popover外部关闭事件捕获问题

针对你遇到的点击TipKit Popover外部关闭时无法触发后续提示的问题,可以通过监听Tip的展示状态变化来实现,无需依赖ViewController的 dismissal 代理或isBeingDismissed属性,具体方案如下:

核心思路

TipKit的Tip结构体本身支持通过Observation监听其isDisplayed属性变化,无论用户是点击关闭按钮还是点击外部区域关闭Popover,只要提示从显示状态变为隐藏,就能捕获到这个变化,进而触发第二个提示的展示条件。

具体实现步骤

  1. 调整Tip结构体的触发规则
    确保FreezeTip的显示规则可被外部状态控制,示例如下:

    struct FreezeTip: Tip {
        @Parameter
        static var pauseTipDisplayed: Bool = false
        
        var title: Text {
            Text("冻结操作提示")
        }
        
        var rules: [Rule] {
            #Rule(Self.$pauseTipDisplayed) { $0 == true }
        }
    }
    
  2. 在ViewController中监听第一个Tip的状态
    在主ViewController中,为PauseTip添加状态监听,当它从显示变为隐藏时,触发第二个提示的展示条件:

    class MainViewController: UIViewController {
        private let pauseTip = PauseTip()
        private var tipObservation: AnyCancellable?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // 初始化TipKit配置
            try? Tips.configure([.displayFrequency(.immediate)])
            
            // 监听PauseTip的显示状态变化
            tipObservation = pauseTip.$isDisplayed
                .removeDuplicates()
                .sink { [weak self] isDisplayed in
                    guard let self = self else { return }
                    // 提示从显示转为隐藏时,触发第二个提示
                    if !isDisplayed {
                        FreezeTip.pauseTipDisplayed = true
                        // 手动触发第二个提示展示(可选,确保即时生效)
                        Task {
                            try? await Tips.show(FreezeTip(), in: self.view)
                        }
                    }
                }
            
            // 展示第一个提示
            Task {
                try? await Tips.show(pauseTip, in: view)
            }
        }
    }
    

为什么之前的方案失效?

  • isBeingDismissed检测:TipKit的Popover由系统内部的TipUIPopoverViewController管理,点击外部关闭时,该控制器的状态不会同步到你的主ViewController,因此无法通过isBeingDismissed捕获事件。
  • presentationControllerDidDismiss代理:TipUIPopoverViewController属于iOS17私有API,无法直接持有其实例并设置代理,导致代理方法无法触发。

额外优化

若无需依赖Parameter触发,也可直接在监听回调中调用Tips.show()展示第二个提示,跳过参数同步环节,避免状态延迟问题。

内容的提问来源于stack exchange,提问作者rafi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 07:40:06