首页 > 解决方案 > 包含特定字符时,UILabel 文本在 PDF 中重复

问题描述

我正在生成一个类似的 PDF:

  1. UIGraphicsBeginPDFContextToFile
  2. layer.render(in: context)
  3. UIGraphicsEndPDFContext

昨天,我找到了一个使所有文本基于向量的修复程序(基本上这个答案https://stackoverflow.com/a/9056861/897465)。

效果很好,文本是矢量和可搜索的,等等。

除了一件恼人的事情。

每次 aUILabel包含字符“Å”时,PDF 中的文本都会出现重复,如下图所示。可能还有其他字符会导致这种情况。在此处输入图像描述

我有一个小例子来演示它。如果您在模拟器中运行此程序,您将获得一个 pdf /tmp/test.pdf,您可以在其中自己查看问题。

我想我应该提交一个 rdar,但我真的想要一些好的解决方法(好意思是不检查是否label.text包含“Å”)。由于我不认为这是 Apple 会解决的问题,因此考虑到以 ( 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)
        }
    }

}

标签: iospdfuikituilabel

解决方案


推荐阅读