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

iOS Swift生成PDF后无法复制文本问题求助

解决iOS Swift生成PDF无法复制文本的问题

嘿,我刚好碰到过这个问题!你现在生成PDF的方式应该是把UILabel当成位图渲染进去的(比如用drawHierarchy(in:afterScreenUpdates:)这类方法),这种方式生成的PDF里,文本其实是一张图片的一部分,自然没法选中复制。要解决这个问题,得直接把文本作为原生的文本对象写入PDF,而不是渲染视图。

下面给你两种靠谱的实现方式:

方式一:用UIKit直接绘制文本(简单场景首选)

这种方法适合简单的文本排版,代码简洁,直接把文本绘制到PDF上下文里,生成的文本完全支持选择复制:

import UIKit

func generateSelectablePDF() -> Data {
    // 定义PDF页面尺寸(标准Letter纸大小)
    let pageSize = CGSize(width: 612, height: 792)
    let pageBounds = CGRect(origin: .zero, size: pageSize)
    
    // 创建PDF上下文
    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, pageBounds, nil)
    UIGraphicsBeginPDFPageWithInfo(pageBounds, nil)
    
    guard let context = UIGraphicsGetCurrentContext() else {
        UIGraphicsEndPDFContext()
        return pdfData as Data
    }
    
    // 配置文本内容和样式
    let targetText = "Bonjour"
    let textAttributes: [NSAttributedString.Key: Any] = [
        .font: UIFont.systemFont(ofSize: 24, weight: .regular),
        .foregroundColor: UIColor.black
    ]
    
    // 计算文本居中的位置
    let textSize = targetText.size(withAttributes: textAttributes)
    let textRect = CGRect(
        x: (pageSize.width - textSize.width) / 2,
        y: (pageSize.height - textSize.height) / 2,
        width: textSize.width,
        height: textSize.height
    )
    
    // 直接绘制文本到PDF上下文(关键!这步生成的是原生文本)
    targetText.draw(in: textRect, withAttributes: textAttributes)
    
    // 结束PDF上下文
    UIGraphicsEndPDFContext()
    
    return pdfData as Data
}

方式二:用Core Text处理复杂排版

如果你的文本需要更复杂的样式(比如多行、富文本、自定义字体),Core Text是更好的选择:

import UIKit
import CoreText

func generateSelectablePDFWithCoreText() -> Data {
    let pageSize = CGSize(width: 612, height: 792)
    let pdfData = NSMutableData()
    
    UIGraphicsBeginPDFContextToData(pdfData, CGRect(origin: .zero, size: pageSize), nil)
    UIGraphicsBeginPDFPageWithInfo(CGRect(origin: .zero, size: pageSize), nil)
    
    guard let context = UIGraphicsGetCurrentContext() else {
        UIGraphicsEndPDFContext()
        return pdfData as Data
    }
    
    // 翻转坐标系(Core Text的坐标系和UIKit方向相反)
    context.textMatrix = .identity
    context.translateBy(x: 0, y: pageSize.height)
    context.scaleBy(x: 1.0, y: -1.0)
    
    // 创建富文本(支持更多样式)
    let attributedText = NSAttributedString(string: "Bonjour", attributes: [
        .font: CTFontCreateWithName("HelveticaNeue" as CFString, 24, nil),
        .foregroundColor: UIColor.black.cgColor
    ])
    
    // 创建排版帧,指定文本显示区域
    let frameSetter = CTFramesetterCreateWithAttributedString(attributedText as CFAttributedString)
    let displayPath = CGPath(rect: CGRect(x: 0, y: pageSize.height/2 - 12, width: pageSize.width, height: 24), transform: nil)
    let textFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, attributedText.length), displayPath, nil)
    
    // 绘制文本
    CTFrameDraw(textFrame, context)
    
    UIGraphicsEndPDFContext()
    
    return pdfData as Data
}

关键注意点

  • 绝对避免用drawHierarchy或render(in:)这类视图渲染方法生成PDF,除非你确实需要把视图当成图片插入。
  • 如果要把整个复杂UI转换成可选择的PDF,你需要遍历视图层级,提取每个文本元素的内容、字体、位置等信息,然后用上面的方法逐个绘制,而不是直接渲染整个视图。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:15:22