为什么在iOS中显示为PDF的底层表格单元格会被截断?

时间:2021-11-13 22:18:43

Question

问题

I have an iOS app that takes an html file, turns it into a PDF, and displays it to a WebKit web view. I have a weird problem where the bottom table cell gets cut off when I display to PDF. The weird thing is that the bottom table is only cut off when the text is centered. If it is left-aligned, everything works fine. Why does this happen?

我有一个iOS应用程序,它接收一个html文件,将它转换成PDF格式,并将它显示到WebKit web view中。我有一个奇怪的问题,当我显示到PDF时,底部的表格单元格被切断了。奇怪的是,只有在文本居中时,底部的表才会被截断。如果它是左对齐的,一切都没问题。这为什么会发生?

Please note that I am not looking for a work around solution. Rather, I am seeking to understand why this happens. Is this a bug in iOS? Or did I miss something?

请注意,我并不是在寻找解决方案。相反,我正在试图理解为什么会发生这种情况。这是iOS中的bug吗?还是我漏掉了什么?

Overview

概述

In the image below, there are two tables <table>. One table is large, has a reddish (coral) background, and has a height of 505px. The other table is below the first with a white background (height is not set). Both have some text. The text is centered for both tables.

在下图中,有两个表

。一张桌子很大,有红色(珊瑚)背景,高度为505px。另一个表格在第一个表格下面,背景为白色(不设置高度)。都有一些文本。文本以两个表为中心。

The navbar title shows the details of the current view. For example, as shown in the image below, a title of PDF Landscape 505 means that the view shows a PDF in landscape dimensions with a main table height of 505px.

导航栏标题显示了当前视图的详细信息。例如,如下图所示,PDF景观505的标题意味着该视图显示一个PDF格式的景观维度,主表高度为505px。

为什么在iOS中显示为PDF的底层表格单元格会被截断?

The Problem

这个问题

The problem arises when I increase the height by 10px. In the image below, the main table height is 515px and the lower table is now cut off.

当我将高度增加10px时,问题就出现了。在下面的图片中,主表高度为515px,下表现在被切断。

为什么在iOS中显示为PDF的底层表格单元格会被截断?

Take the exact same html and css code and change only the text-alignment to be left-aligned. Now the lower table is not cut off anymore. I also changed the background color to green for distinction. Green means that text is left-aligned. Red means that text is centered.

使用相同的html和css代码,只更改文本对齐方式为左对齐。现在下表不再被切断。我还将背景颜色改为绿色以区分。绿色表示文本是左对齐的。红色表示文本居中。

为什么在iOS中显示为PDF的底层表格单元格会被截断?

The following image shows a main-table height of 745px and still the lower table is not cut off because it is left-aligned.

下面的图像显示了主表的高度为745px,但由于左对齐,下表仍然没有被截断。

为什么在iOS中显示为PDF的底层表格单元格会被截断?

Code

代码

Below is the html code used for this test.

下面是用于测试的html代码。

<!DOCTYPE html>
<html>
<head>
  <title>#COLOR#</title>
  <meta charset="utf-8">
  <style>
  table, th, td {
    border-collapse: collapse;
    border: 3px solid black;
    text-align: #ALIGN#;
  }
  table.main-table {
    width: 1012px;
    height: #HEIGHT#px;
    background-color: #COLOR#;
  }
  table.bottom-table {
    width: 1012px;
  }
  </style>
</head>

<body>

  <table class="main-table">
    <tr><td>Hello World.</td></tr>
  </table>
  <table class="bottom-table">
    <tr><td>This text gets cut off when centered. It does *not* get cut when left-aligned.</td></tr>
  </table>

</body>
</html>

In MyViewController, the getHTML() function pulls the html source from sample.html. The function then replaces #ALIGN#, #COLOR#, and #HEIGHT# with their respective values.

在MyViewController中,getHTML()函数从sample.html提取html源代码。然后该函数将#ALIGN#、#COLOR#和#HEIGHT#替换为各自的值。

func getHTML() -> String? {
    let htmlPath: String? = Bundle.main.path(forResource: htmlResource, ofType: "html")
    guard let path = htmlPath else { return nil }
    do {
        // Load the HTML template code into a String variable.
        var html = try String(contentsOfFile: path)
        html = html.replacingOccurrences(of: "#HEIGHT#", with: tableHeight.description)
        html = html.replacingOccurrences(of: "#COLOR#", with: colorState.rawValue)
        html = html.replacingOccurrences(of: "#ALIGN#", with: alignState.rawValue)
        return html
    } catch {
        print("Error: " + error.localizedDescription)
    }
    return nil
}

The PDFBuilder class handles the PDF creation with one function:

PDFBuilder类使用一个函数处理PDF创建:

static func exportHTMLToPDF(html: String, frame: CGRect) -> Data {
    // Set a printable frame and inset                
    let pageFrame = frame
    let insetRect = pageFrame.insetBy(dx: 10.0, dy: 10.0)

    // Create a UIPrintPageRenderer and set the paperRect and printableRect using above values.
    let pageRenderer = UIPrintPageRenderer()
    pageRenderer.setValue(pageFrame, forKey: "paperRect")
    pageRenderer.setValue(insetRect, forKey: "printableRect")

    // Create a printFormatter and pass the HTML code as a string.
    let printFormatter = UIMarkupTextPrintFormatter(markupText: html)

    // Add the printFormatter to the pageRenderer
    pageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)

    // This data var is where the PDF will be stored once created.
    let data = NSMutableData()

    // This is where the PDF gets drawn.
    UIGraphicsBeginPDFContextToData(data, pageFrame, nil)
    UIGraphicsBeginPDFPage()
    pageRenderer.drawPage(at: 0, in: UIGraphicsGetPDFContextBounds())
    print("bounds: " + UIGraphicsGetPDFContextBounds().debugDescription)        
    UIGraphicsEndPDFContext()

    return data as Data
} 

This project is also on Github: https://github.com/starkindustries/PrintPDFTest

这个项目也在Github上:https://github.com/starkindustries/PrintPDFTest

Troubleshooting Steps Taken

故障排除步骤

  1. Dimensions: I tried playing around with the size of the PDF dimensions. This did not make a difference in the result.
  2. 尺寸:我尝试使用PDF的尺寸。这对结果没有影响。
  3. Columns: I tried using multiple columns instead of just one. Same problem; no difference.
  4. 列:我尝试使用多个列而不是一个列。同样的问题;没有区别。
  5. Tables: I tried using just one table instead of two. With one table and two cells, the bottom cell still gets cut off when text is centered; bottom cell does not get cut when text is left-aligned.
  6. 桌子:我试着只用一张桌子,而不是两张。在一个表和两个单元格中,当文本居中时,底部的单元格仍然被截断;当文本左对齐时,底部单元格不会被剪切。
  7. iPhones: I tried simulating on different iPhone devices (iPhone 6s, iPhone 8, iPad Pro). Same issue.
  8. iPhone:我试着在不同的iPhone设备上进行模拟(iPhone 6s, iPhone 8, iPad Pro)。相同的问题。
  9. Div: If you use a div instead of a second table, the problem is magically fixed. But why does a div work and not a table?
  10. Div:如果您使用Div而不是第二个表,那么问题会神奇地得到修复。但是为什么div可以工作而不是表格呢?

App Notes

应用笔记

The top toolbar has two buttons: green and red. Green makes the text left-aligned. Red makes the text centered.

顶部工具栏有两个按钮:绿色和红色。绿色使文本左对齐。红色使文字居中。

为什么在iOS中显示为PDF的底层表格单元格会被截断?

The bottom toolbar has five buttons: rewind, html, portrait, landscape, and fast forward. The rewind button reduces the main table's height by 10px. Fast forward increases the height by 10px. The html button shows the html view. Portrait and landscape show PDF's in their respective orientations.

底部的工具栏有五个按钮:后退、html、纵向、横向和快速前进。rewind按钮减少了主表的高度10px。快进增加高度10px。html按钮显示html视图。肖像和景观显示PDF在各自的方向。

为什么在iOS中显示为PDF的底层表格单元格会被截断?

1 个解决方案

#1


0  

I think this is the problem:

我认为这就是问题所在:

  table, th, td {
    border-collapse: collapse;
    border: 3px solid black;
    text-align: #ALIGN#;
  }

Setting rule on the table, & the th, td looks like trouble to me (having troubleshot more than a few pdf rendering issues)

在表上设置规则,以及th、td对我来说似乎很麻烦(有超过几个pdf渲染问题的疑难解答)

If it's not the text-align, as per DeadLock's comment... then it could be the border-collapse that's being applied to the td (I think it just needs to go on the table).

如果不是文本对齐,按照死锁的注释……那么就有可能是边界塌陷被应用到td(我认为它只需要放到桌面上)。

Another frontend debugging-tip for this kind of thing is:

这类事情的另一个前端调试技巧是:

* {border:1px solid #f00} or * {box-shadow: inset 0 0 1px #f00} (the latter doesn't risk adding anything to the proportions of elements, but may not render in a pdf view) those rules will help you see at a glance what each of your edits is doing to the layout, rather than having to turn to the element inspector.

* {边界:1 px固体# f00 }或* {不必:插图0 0 1 px # f00 }(后者不添加任何风险元素的比例,但可能不会在一个pdf呈现视图)这些规则将帮助您一眼就看到你的每一个编辑布局,而不必向元素检查员。

Also, make sure you have a good understanding of how the table element renders by default in that dom.

此外,请确保您对表元素在该dom中的默认呈现方式有很好的理解。

In declaring rules for both element and element.class you may have thrown something off. Compare to behavior with no styles then add them back one by one.

在声明元素和元素的规则时。类您可能已经抛出了一些东西。将没有样式的行为进行比较,然后将它们逐一添加回来。

I took a shot at rewriting your code:

我试着重写你的代码:

<!DOCTYPE html>
<html>
<head>
  <title>COLOR</title>
  <meta charset="utf-8">
  <style>
  table{
    border-collapse: collapse;
  }
  th{

  }
  td {
    border-width:3px;
    border-style:solid;
    border-color:#000000;
  }
  tr{
    text-align: center;
  }
  table.main-table {
    width: 1012px;
    height: 515px; /* There's a lot you can do here instead of height: 515px; if needed I can elaborate. I'm guessing the content is varible-height? does flex-box make it through the pdf-generator?  */
    background-color: #ccc;
  }
  table.bottom-table {
    width: 1012px;
  }
  </style>
</head>

<body>

  <table class="main-table">
    <tr><td>Hello World.</td></tr>
  </table>
  <table class="bottom-table">
    <tr><td>This text gets cut off when centered. It does *not* get cut when left-aligned.</td></tr>
  </table>

</body>
</html>

Other questions:

其他问题:

Can you inspect it in emulation with a debugger? Or, can you change the way the pdf is output to show errors?

你能用调试器在模拟中检查它吗?或者,您可以更改pdf的输出方式来显示错误吗?

Could the heights of the rows be percentages?

行的高度可以是百分比吗?

#1


0  

I think this is the problem:

我认为这就是问题所在:

  table, th, td {
    border-collapse: collapse;
    border: 3px solid black;
    text-align: #ALIGN#;
  }

Setting rule on the table, & the th, td looks like trouble to me (having troubleshot more than a few pdf rendering issues)

在表上设置规则,以及th、td对我来说似乎很麻烦(有超过几个pdf渲染问题的疑难解答)

If it's not the text-align, as per DeadLock's comment... then it could be the border-collapse that's being applied to the td (I think it just needs to go on the table).

如果不是文本对齐,按照死锁的注释……那么就有可能是边界塌陷被应用到td(我认为它只需要放到桌面上)。

Another frontend debugging-tip for this kind of thing is:

这类事情的另一个前端调试技巧是:

* {border:1px solid #f00} or * {box-shadow: inset 0 0 1px #f00} (the latter doesn't risk adding anything to the proportions of elements, but may not render in a pdf view) those rules will help you see at a glance what each of your edits is doing to the layout, rather than having to turn to the element inspector.

* {边界:1 px固体# f00 }或* {不必:插图0 0 1 px # f00 }(后者不添加任何风险元素的比例,但可能不会在一个pdf呈现视图)这些规则将帮助您一眼就看到你的每一个编辑布局,而不必向元素检查员。

Also, make sure you have a good understanding of how the table element renders by default in that dom.

此外,请确保您对表元素在该dom中的默认呈现方式有很好的理解。

In declaring rules for both element and element.class you may have thrown something off. Compare to behavior with no styles then add them back one by one.

在声明元素和元素的规则时。类您可能已经抛出了一些东西。将没有样式的行为进行比较,然后将它们逐一添加回来。

I took a shot at rewriting your code:

我试着重写你的代码:

<!DOCTYPE html>
<html>
<head>
  <title>COLOR</title>
  <meta charset="utf-8">
  <style>
  table{
    border-collapse: collapse;
  }
  th{

  }
  td {
    border-width:3px;
    border-style:solid;
    border-color:#000000;
  }
  tr{
    text-align: center;
  }
  table.main-table {
    width: 1012px;
    height: 515px; /* There's a lot you can do here instead of height: 515px; if needed I can elaborate. I'm guessing the content is varible-height? does flex-box make it through the pdf-generator?  */
    background-color: #ccc;
  }
  table.bottom-table {
    width: 1012px;
  }
  </style>
</head>

<body>

  <table class="main-table">
    <tr><td>Hello World.</td></tr>
  </table>
  <table class="bottom-table">
    <tr><td>This text gets cut off when centered. It does *not* get cut when left-aligned.</td></tr>
  </table>

</body>
</html>

Other questions:

其他问题:

Can you inspect it in emulation with a debugger? Or, can you change the way the pdf is output to show errors?

你能用调试器在模拟中检查它吗?或者,您可以更改pdf的输出方式来显示错误吗?

Could the heights of the rows be percentages?

行的高度可以是百分比吗?