Calculating text size with NSLayoutManager

I'm working on a view that uses the TextKit framework to typeset text in columns like this: Column Text Layout

I am using UIView

cross-cut borders (black rectangle) to calculate 10 CGRects

, which I then convert to NSTextContainers

(red rectangles). In drawRect:

I pass them in NSLayoutManager

, which type and draw glyphs for me.

My question is: How can I calculate the number of columns required? I can draw a constant number of columns, but with different text lengths, I need to adjust the number of columns programmatically.

I found a method [NSLayoutManager glyphRangeForTextContainer:]

that returns a range of length 0 when the text container is left empty. So I could create loops to create text containers and use that method to determine if more containers are needed. However, this method is considered ineffective as it triggers a layout computation and I am not happy to run it in a loop, perhaps hundreds of times.

There must be a better way!

Thanks for your answers, Pete.

+3


source to share


1 answer


Well, after some searching around within TextKit, I finally found the answer.

My code runs in a loop like this:

while ([self needsMoreColumns]) {
    [self addColumn];
}

...

- (BOOL)needsMoreColumns {
    // Always create at least one column
    if (self.layoutManager.textContainers.count == 0)
        return YES;

    // Find out the glyph range of the last column
    NSRange range = [self.layoutManager glyphRangeForTextContainer:[self.layoutManager.textContainers lastObject]];
    NSUInteger glyphs = [self.layoutManager numberOfGlyphs];

    // Compare it with the number of glyphs
    return range.location + range.length < glyphs;
}

      



I have not included the method [self addColumn]

as this is not a problem. It just uses the geometry of my layout and the position of the last column (if any) to calculate the CGRect

next one. It then creates NSTextContainer

with the appropriate size and stores the origin

rectangle property in a dedicated array for drawing purposes.

I also discovered methods [NSLayoutManager firstUnlaidCharacterIndex]

and [NSLayoutManager firstUnlaidGlyphIndex]

, but they don't seem to work as expected. After placing three columns of text in one column, they returned the length of the entire line, not the position of the first character, which did not fit in the first column. This is why I rather used a range based approach.

To keep all people safe! Pete.

+3


source







All Articles