Apple 的 PDFKit:带有 Ink 注释的免费绘图

Posted

技术标签:

【中文标题】Apple 的 PDFKit:带有 Ink 注释的免费绘图【英文标题】:Apple's PDFKit: Free draw with Ink annotation 【发布时间】:2018-02-21 20:53:43 【问题描述】:

我只想使用 PDFKit 在 PDF 文件上绘图。这听起来很简单,但我遇到了很多麻烦。从文档中,墨水注释似乎适合于此。这是我的代码:

/// Adds a new annotation
func addAnnotation(color: UIColor, point: CGPoint) 
    currentPage = pdfView.page(for: point, nearest: false)

    // Here I convert the coordinates to the document and create a new annotation
    if currentPage != nil 
        let topRight = pdfView.convert(pdfView.frame.topRightCorner, to: currentPage!)
        newAnnotation = PDFAnnotation(bounds: CGRect(origin: .zero, size: CGSize(width: topRight.x, height: topRight.y)), forType: .ink, withProperties: nil)
        newAnnotation!.color = color
        currentPage!.addAnnotation(newAnnotation!)
    
    else 
        newAnnotation = PDFAnnotation()
    


/// Adds a new path, maybe a new annotation
func addPath(color: UIColor, point: CGPoint, lineWidth: CGFloat) 

    // Create annotation
    if newAnnotation == nil 
        addAnnotation(color: color, point: point)
    

    guard currentPage != nil else  return 

    let convertedPoint = pdfView.convert(point, to: currentPage!)

    // Create initial path
    let path = UIBezierPath()
    path.lineWidth = 200
    path.move(to: convertedPoint)
    path.addLine(to: convertedPoint)
    newAnnotation!.add(path)


/// Updates the last drawn annotation
func updatePath(point: CGPoint) 
    if let annotation = newAnnotation, let page = currentPage 
        let convertedPoint = pdfView.convert(point, to: page)
        let lastPath = annotation.paths!.last!
        lastPath.addLine(to: convertedPoint)
        annotation.remove(lastPath)
        annotation.add(lastPath)
    

我的主要问题是性能。我编写所有这些代码只是为了拥有一个功能绘图程序。我在这个过程中所理解的:

将注释中的路径分组而不是每个路径有一个注释似乎更有效。所以我添加了 addAnnotation() 方法,它有时会创建一个新的注解。 创建注释时的'bounds' 属性对性能有很大影响。将此属性设置为页面的边界会使程序非常慢。但问题是,在用户完成绘制之前我不知道注释的边界......

我有一个方法 touchMoved(),我想在路径中添加一个点。起初,我只是在做:

if let annotation = newAnnotation, let page = currentPage 
    let convertedPoint = pdfView.convert(point, to: page)
    let lastPath = annotation.paths!.last!
    lastPath.addLine(to: convertedPoint)

但路径没有更新,所以我添加了以下行:

    annotation.remove(lastPath)
    annotation.add(lastPath)

事实证明这在性能方面非常糟糕(路径有时会消失,然后再出现)。

我假设有更好的方法来做这一切,但我找不到任何好的例子。如果您在 PDFKit 上有一个 Ink 注释的工作示例,那也很棒。

附带问题:在我的代码中,我将 bezierPath 的 lineWidth 设置为 200。这是因为我想更改注释的 lineWidth,但更改 bezierPath 的 lineWidth 似乎并没有改变任何东西。有什么想法吗?

【问题讨论】:

【参考方案1】:

我的观察与你的相似。我发现操作 PDFAnnotation 很麻烦,主要是因为一个错误(PDFAnnotation with PDFAnnotationSubtype equal to .widget is not refreshing its appearance after adding it to PDFPage)。 删除它们并将其读取到PDFView 的技巧是一种令人讨厌的解决方法。

也许尝试不同的方法会更好? 例如:

    在 PDFView 顶部使用CoreGraphics 绘制(透明)CGLayer。 将绘图层转换为UIImage。 将带有图像的注释添加到您的PDFView。您可以查看 Apple 示例以了解操作方法。 https://developer.apple.com/library/content/samplecode/PDFAnnotationEditor/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004035

【讨论】:

这似乎是一个很好的解决方法,我会研究一下。 这确实有效。您对 lineWidth 问题有任何想法吗?对于这个解决方案,这一点更为重要:我在一个具有一定宽度的图层上绘图,但是当我在最后添加它作为注释时,绘图的宽度始终为 1,我无法更改它。如何更改注释的宽度,有什么方法可以将 Core Graphics 中的宽度转换为文档,以便添加时绘图看起来相同?谢谢 我没有发现注释宽度有任何问题。如果您不介意,请为其添加单独的问题。源代码也会很有帮助。

以上是关于Apple 的 PDFKit:带有 Ink 注释的免费绘图的主要内容,如果未能解决你的问题,请参考以下文章

使用 PDFKIt iOS 11 创建 PDF 注释

Apple PDFKit - 带有验证脚本的 PDF 问题。

PDFKit / PDFView 禁用与表单注释的交互

iOS 11 PDFKit 墨水注释 - 无法填充 UIBezierPath

pdfObjective-C 中 PDFKit 的大纲

PDFKit 交换注释的内容