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

Data/NSData类型存储的PDF数据转换为UIImage返回nil问题求助

问题根本原因

UIImage(data:) 方法仅支持PNG、JPEG、TIFF等标准位图格式的二进制数据,PDF是矢量文档格式,无法直接通过该方法解析加载,这是你始终得到nil的核心原因。

额外问题说明

你现有代码中使用固定2秒延时等待下载完成的逻辑非常不稳定,下载耗时受网络环境影响波动极大,建议直接将图片渲染逻辑放到下载完成的回调方法中执行,避免出现数据还没下载完就开始转换的问题。

解决方案代码实现

第一步:添加PDF转UIImage的工具方法

在你的ViewPDF类中添加如下通用转换方法,支持指定页码、按屏幕清晰度渲染:

func pdfDataToImage(_ data: Data, pageIndex: Int = 0, scale: CGFloat = UIScreen.main.scale) -> UIImage? {
    // 构造PDF文档对象
    guard let provider = CGDataProvider(data: data as CFData),
          let pdfDocument = CGPDFDocument(provider),
          let pdfPage = pdfDocument.page(at: pageIndex + 1) else { // CGPDFDocument的页码从1开始计数
        return nil
    }
    
    // 获取PDF页面原始尺寸,按屏幕缩放比计算渲染尺寸保证清晰度
    let pageRect = pdfPage.getBoxRect(.mediaBox)
    let renderSize = CGSize(width: pageRect.width * scale, height: pageRect.height * scale)
    
    // 渲染PDF页为位图
    let renderer = UIGraphicsImageRenderer(size: renderSize)
    let renderedImage = renderer.image { context in
        let cgContext = context.cgContext
        // 坐标系变换修正PDF上下颠倒的问题
        cgContext.translateBy(x: 0, y: renderSize.height)
        cgContext.scaleBy(x: scale, y: -scale)
        cgContext.drawPDFPage(pdfPage)
    }
    return renderedImage
}

第二步:修改下载回调逻辑

删掉test方法中2秒延时后的图片赋值逻辑,把转换渲染逻辑放到下载完成回调processDownloadedPDF中:

@objc func processDownloadedPDF(ticket: GTLRServiceTicket,
                          finishedWithObject file: GTLRDataObject,
                          error : NSError?) {
    if let error = error {
        print("Drive Download Error: \(error)")
        let alert = UIAlertController(title: "Google Drive Download Error", message:
            "Oops - Something went wrong! Error \(error.code): \(error.localizedDescription)", preferredStyle: .actionSheet)
        alert.addAction(UIAlertAction(title: "Ok", style: .default))
        self.present(alert, animated: true)
        return
    }
    
    // 主线程更新UI
    DispatchQueue.main.async { [weak self] in
        guard let self = self,
              let pdfImage = self.pdfDataToImage(file.data) else {
            return
        }
        self.PDF.image = pdfImage
    }
    print("Drive Download Worked")
}

如果你的PDF包含多页,只需循环调用pdfDataToImage方法传入不同的pageIndex参数,生成每页对应的图片后做分页展示即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:06:02