QLPreviewController推入导航栈后编辑PDF无法返回的问题求助
QLPreviewController编辑PDF后返回卡顿无响应问题排查
问题现象
使用QLPreviewController编辑PDF,推入导航栈后功能正常,但添加注释后点击返回按钮无法回到上一个控制器——点击一次后返回按钮变灰,随后界面陷入卡顿状态。
相关代码
func openPDF(file:FileModel){ selectedFile = file let previewController = CustomQLViewController() previewController.file = self.selectedFile previewController.dataSource = self previewController.delegate = self self.navigationController?.pushViewController(previewController, animated: true) } func numberOfPreviewItems(in controller: QLPreviewController) -> Int { return 1 } func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { //return getFileURLFromFileModel()! as QLPreviewItem let previeItem = PreviewItem(url: getFileURLFromFileModel(), title: selectedFile?.name) return previeItem } func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode { return .updateContents } func previewController(_ controller: QLPreviewController, didUpdateContentsOf previewItem: QLPreviewItem) { print("updated") } func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) { }
排查方向与解决方案
1. 完善编辑后文件的保存逻辑
didSaveEditedCopyOf方法未处理修改后的文件是核心问题之一。QLPreviewController在编辑完成后会生成临时文件,若不将其替换原文件,控制器会持续持有临时资源,导致状态异常,引发返回卡顿。补全该方法的实现:
func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) { guard let originalURL = getFileURLFromFileModel() else { return } do { // 删除原文件(若存在) if FileManager.default.fileExists(atPath: originalURL.path) { try FileManager.default.removeItem(at: originalURL) } // 将修改后的临时文件移动到原路径 try FileManager.default.moveItem(at: modifiedContentsURL, to: originalURL) // 更新预览项的URL(如果PreviewItem支持可变属性) if let item = previewItem as? PreviewItem { item.url = originalURL } } catch { print("保存编辑文件失败:\(error.localizedDescription)") } }
2. 检查自定义PreviewItem的协议实现
确保PreviewItem正确实现QLPreviewItem协议,避免URL或title的getter存在异步操作或无效返回:
class PreviewItem: NSObject, QLPreviewItem { var url: URL var title: String? init(url: URL?, title: String?) { self.url = url ?? URL(fileURLWithPath: "") self.title = title super.init() } var previewItemURL: URL? { return url } var previewItemTitle: String? { return title } }
3. 排查CustomQLViewController的自定义逻辑
如果CustomQLViewController重写了导航栏返回按钮、viewWillDisappear或popViewController相关方法,可能干扰了正常的返回流程:
- 移除对返回按钮的自定义拦截逻辑
- 确保未在编辑状态下执行耗时的资源清理操作
4. 确保所有UI操作在主线程执行
QLPreviewController的所有交互必须在主线程完成,若openPDF方法是在后台线程调用的,需切换到主线程:
func openPDF(file:FileModel){ DispatchQueue.main.async { self.selectedFile = file let previewController = CustomQLViewController() previewController.file = self.selectedFile previewController.dataSource = self previewController.delegate = self self.navigationController?.pushViewController(previewController, animated: true) } }
5. 避免循环引用
检查CustomQLViewController的代理属性是否为弱引用,防止当前控制器与预览控制器形成循环引用导致内存泄漏:
class CustomQLViewController: QLPreviewController { weak var delegate: QLPreviewControllerDelegate? // 必须使用weak修饰 // 其他自定义代码 }
内容的提问来源于stack exchange,提问作者Ranadhir
相关产品推荐
相关产品推荐

