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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:53:14