0
votes

Goal is to have a single NSAttributedString with a larger line height between paragraphs than within a paragraph, a fairly simple and common use case it seems to me. Here's my code:

NSMutableParagraphStyle *firstParagraphStyle = [[NSMutableParagraphStyle alloc] init];
firstParagraphStyle.lineHeightMultiple = 3.0;
NSMutableParagraphStyle *secondParagraphStyle = [[NSMutableParagraphStyle alloc] init];
secondParagraphStyle.lineHeightMultiple = 1.0;

NSAttributedString *title = [[NSAttributedString alloc] initWithString:@"Title"
                                                            attributes:@{NSParagraphStyleAttributeName: firstParagraphStyle}];
NSAttributedString *bodyTop = [[NSAttributedString alloc] initWithString:@"\u2029Body 1"
                                                              attributes:@{NSParagraphStyleAttributeName: secondParagraphStyle}];
NSAttributedString *bodyBottom = [[NSAttributedString alloc] initWithString:@"\u2029Body 2 line 1\u2028Body 2 line 2"
                                                              attributes:@{NSParagraphStyleAttributeName: secondParagraphStyle}];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:title];
[attributedString appendAttributedString:bodyTop];
[attributedString appendAttributedString:bodyBottom];

All four lines end up with the same line spacing of 3.0. In fact, when I remove the attributes dictionary entirely and simply do:

NSAttributedString *title = [[NSAttributedString alloc] initWithString:@"Title"];
NSAttributedString *bodyTop = [[NSAttributedString alloc] initWithString:@"\u2029Body 1"];
NSAttributedString *bodyBottom = [[NSAttributedString alloc] initWithString:@"\u2029Body 2 line 1\u2028Body 2 line 2"];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:title];
[attributedString appendAttributedString:bodyTop];
[attributedString appendAttributedString:bodyBottom];
[attributedString addAttribute:NSParagraphStyleAttributeName
                         value:firstParagraphStyle
                         range:NSMakeRange(0, 1)];
[attributedString addAttribute:NSParagraphStyleAttributeName
                         value:secondParagraphStyle
                         range:NSMakeRange(1, attributedString.length - 1)];

it still renders all three paragraphs using line height multiple of 3.0. It seems that whatever the first paragraph style I apply to the string is, that's the one that applies to all subsequent lines and paragraphs!

Why doesn't using the special paragraph separator character \u2029 as Apple suggests here allow for more than one paragraph style within a single NSAttributedString? I'd prefer not to break into multiple UILabels.

Thanks in advance to anyone with deep Core Text knowledge on this subject.

1
I think it works for me. Try to add @{NSBackgroundAttributeName:aDifferentColorForEachSubStringLikeTitleBodyTopBodyBottom} to see what it does, and try with different lineHeightMultiple. - Larme
@Larme yeah I've set various colors and fonts with no problems. The issue is only with the paragraph style. You say it works for you. Mind posting some sample code that works for you? Much appreciated. - Tyler Sheaffer

1 Answers

0
votes

Ended up getting this working. Turns out when I set alignment on the subsequent UILabel to .textAlignment = NSTextAlignmentCenter that messed up the paragraph style for the entire attributedText.

So the lesson is: If you're using multiple paragraph styles, don't set any corresponding properties on the UILabel or your behavior will be clobbered by the first paragraph style the label sees, even when the properties aren't related (e.g. line height and text alignment).