我正在生成一个类似以下内容的PDF文件:
-
UIGraphicsBeginPDFContextToFile
-
layer.render(in: context)
-
UIGraphicsEndPDFContext
昨天,我找到了一个修复方法,使所有文本向量都基于这个答案(基本上就是这个答案)
https://stackoverflow.com/a/9056861/897465
).
这真的很好,文本是向量和可搜索的,等等。
除了一件恼人的事。
每次
UILabel
包含字符“”,文本在PDF中有点重复,如下图所示。可能还有其他角色也会导致这种情况。
下面我举了一个小例子来说明这一点。如果你在模拟器中运行这个程序,你会在
/tmp/test.pdf
在那里你可以看到自己的问题。
我想我应该提交一个rdar,但我真的希望有一些好的解决方法(好的意思是不检查
label.text
包含“Ã
”)。考虑到整个解决方案,我认为苹果不会解决这个问题(
PDFLabel
).
import UIKit
class PDFLabel: UILabel {
override func draw(_ layer: CALayer, in ctx: CGContext) {
let isPDF = !UIGraphicsGetPDFContextBounds().isEmpty
if !layer.shouldRasterize && isPDF {
draw(bounds)
} else {
super.draw(layer, in: ctx)
}
}
}
func generatePDFWith(_ texts: [String]) {
let paper = CGRect(origin: .zero, size: CGSize(width: 876, height: 1239))
UIGraphicsBeginPDFContextToFile("/tmp/test.pdf", paper, [
kCGPDFContextCreator as String: "SampleApp"
])
texts.forEach { text in
UIGraphicsBeginPDFPage()
let v = UIView()
let label = PDFLabel()
label.text = text
label.textColor = .black
v.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
v.addSubview(label)
v.widthAnchor.constraint(equalToConstant: 500).isActive = true
v.heightAnchor.constraint(equalToConstant: 500).isActive = true
label.centerXAnchor.constraint(equalTo: v.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: v.centerYAnchor).isActive = true
v.setNeedsLayout()
v.layoutIfNeeded()
v.layer.render(in: UIGraphicsGetCurrentContext()!)
}
UIGraphicsEndPDFContext();
print("Done!")
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
generatePDFWith([
"Ã
ngavallen",
"Hey Whatsapp?",
"Ãnglavallen",
"Ãrebro",
"Råå",
"RÃ
Ã
",
"Ã
",
"Ã
l",
])
}
}
编辑
:调试几乎没有进展,似乎
draw
函数会被调用两次,第一次调用时,如果它有一个“Ã
”(可能是比框大的任何字符),则会被稍微“关闭”。
因此,这为我修复了它(无论它多么丑陋):
class PDFLabel: UILabel {
var count = 0
override func draw(_ layer: CALayer, in ctx: CGContext) {
let isPDF = !UIGraphicsGetPDFContextBounds().isEmpty
if isPDF {
if count > 0 { draw(bounds) }
count += 1
} else if !layer.shouldRasterize {
draw(bounds)
} else {
super.draw(layer, in: ctx)
}
}
}