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
相关产品推荐
相关产品推荐

