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

如何监听QLPreviewController中PKToolPicker的显示状态?

解决方案

要同时监听键盘弹出和QLPreviewController内部PKToolPicker的显示状态,可以通过以下方式实现:

1. 监听PKToolPicker可见性

QLPreviewController内部的PKToolPicker虽非主动初始化,但可通过PKToolPicker.shared(for:)方法获取与当前预览内容关联的实例,再借助PKToolPickerObserver协议监听其可见性变化。核心是要在预览内容加载完成后获取对应的Picker实例:

修改你的Coordinator类:

class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate, PKToolPickerObserver {
    let parent: QLPDFPreviewController
    weak var toolPicker: PKToolPicker?
    
    init(parent: QLPDFPreviewController) {
        self.parent = parent
        super.init()
        
        // 注册键盘通知
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillShow),
                                               name: UIResponder.keyboardWillShowNotification,
                                               object: nil)
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillHide),
                                               name: UIResponder.keyboardWillHideNotification,
                                               object: nil)
    }
    
    // MARK: - QLPreviewControllerDelegate
    func previewControllerWillDisplayPreviewItem(_ controller: QLPreviewController, for item: QLPreviewItem) {
        // 获取当前预览内容的视图
        guard let previewView = controller.view.subviews.first(where: { $0 is UIScrollView })?.subviews.first else {
            return
        }
        // 获取关联的PKToolPicker
        let picker = PKToolPicker.shared(for: previewView)
        picker.addObserver(self)
        self.toolPicker = picker
    }
    
    func previewControllerDidDismiss(_ controller: QLPreviewController) {
        // 移除观察者,避免内存泄漏
        toolPicker?.removeObserver(self)
        NotificationCenter.default.removeObserver(self)
    }
    
    // MARK: - PKToolPickerObserver
    func toolPickerVisibilityDidChange(_ toolPicker: PKToolPicker) {
        // PKToolPicker可见性变化时执行你的逻辑
        if toolPicker.isVisible {
            // 显示时处理逻辑
            print("ToolPicker 显示")
        } else {
            // 隐藏时处理逻辑
            print("ToolPicker 隐藏")
        }
    }
    
    // MARK: - 键盘通知处理
    @objc func keyboardWillShow(_ notification: Notification) {
        // 键盘弹出时执行你的逻辑
        print("键盘弹出")
    }
    
    @objc func keyboardWillHide(_ notification: Notification) {
        // 键盘隐藏时执行你的逻辑
        print("键盘隐藏")
    }
    
    // 原有的QLPreviewControllerDataSource方法保持不变
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return 1
    }
    
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        guard let url = parent.url else { return NSURL(string: "")! }
        return url as NSURL
    }
    
    func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
        .updateContents
    }
}

2. 关键说明

  • 获取PKToolPicker时机:通过previewControllerWillDisplayPreviewItem方法确保预览内容已加载,此时可获取对应预览视图,进而拿到关联的PKToolPicker实例。
  • 观察者生命周期管理:在预览控制器 dismiss 时,务必移除PKToolPicker和键盘通知的观察者,防止内存泄漏。
  • 兼容性:该方法适用于iOS 14及以上系统(PKToolPickerObserver在iOS 14引入),若需兼容更低版本,需添加版本判断逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:59:51