简体   繁体   中英

Unable to render an NSAttributedString as a 2 column tabbed bullet list in a PDF

I am constructing a large string that is output into a PDF file, but right now, I'd like to have a 2 column, bulleted list in my document. However, I have yet to figure out the correct settings that will allow me to get the desired tabbing effect.

Currently, I am testing the following code:

let mutableString = NSMutableAttributedString()
let words = ["this", "is", "really", "getting", "old"]

let paragraphStyle = NSMutableParagraphStyle()
var tabStops = [NSTextTab]()
let tabInterval: CGFloat = 250.0
for index in 0..<12 {
    tabStops.append(NSTextTab(textAlignment: .left,
                              location: tabInterval * CGFloat(index),
                              options: [:]))
}
paragraphStyle.tabStops = tabStops

for index in 0..<words.count {
    if index != 0 && index % 2 == 0 {
        mutableString.append(NSAttributedString(string: "\n"))
    }
    if index % 2 == 1 {
        let attributedText = NSAttributedString(string: "\t", attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])
        mutableString.append(attributedText)
    }
    let word = words[index]
    let attributedString = NSMutableAttributedString(string: "\u{2022}  \(word)",
        attributes: [:])
    mutableString.append(attributedString)
}

When I feed this into my PDF generator, it produces the following result:

在此输入图像描述

Ultimately, I want "is" and "getting" to be aligned with the middle of the document, so that I can accommodate much larger words.

It turns out that I was in the ballpark, but definitely not close.

The following provides the desired split column effect:

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.tabStops = [
    // 274 would be the midpoint of my document
    NSTextTab(textAlignment: .left, location: 274, options: [:])
]

let string = "\u{2022} This\t\u{2022} is\n\u{2022} getting\t\u{2022} really\n\u{2022} old"

let attributedString = NSAttributedString(
    string: string,
    attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle]
)

在此输入图像描述

For bonus points, should you want to have multiple columns in your document, the following will accomplish this (pardon my crude formatting):

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.tabStops = [
    NSTextTab(textAlignment: .left, location: 100, options: [:]),
    NSTextTab(textAlignment: .left, location: 300, options: [:])
]

let string = "\u{2022} This\t\u{2022} is\t\u{2022} getting\n\u{2022} really\t\u{2022} old"

let attributedString = NSAttributedString(
    string: string,
    attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle]
)

And will look like this:

在此输入图像描述

What is going on here?

So, what I learned here is that the tabStops tells iOS what location within the line to place the tab:

  1. The first tab will go to position 100
  2. The second tab will go to position 300
  3. A third tab will wrap around the document and go to position 100 as well

Regarding tabbing, if you assign a tab with location 0 in the first index, then tabbing to a newline will get it aligned with the left edge.

As to what fixed the issue for me. I was relying on an approach where each component of the string was added as it was encountered. However, this string would fail to format properly. Instead, by merging everything into a single string and applying the attributes seen in my working code, I was able to get it to align properly.

I also tested using the individual components as seen in my question, but with the paragraph style attributes applied as well, and that resulted in a working solution as well.

Based on this, it appears that my mistake was to mix strings that had, and did not have, the desired tabbing behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM