如何监听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
相关产品推荐
相关产品推荐

