I have a NSTextStorage
with long text inside (like 500 pages in a book and more than 9000 on a device for current font). I'm distributing this text for textcontainers this way:
let textStorageLength = defaultTextStorage?.length ?? 0
while layoutManager!.textContainer(forGlyphAt: textStorageLength - 1,
effectiveRange: nil) == nil {
let textContainer = NSTextContainer(size: textContainerSize)
layoutManager!.addTextContainer(textContainer)
pagesCount += 1
}
The problem is that it takes long period of time to init all this containers etc. I already have made some improvements like changing code from using
while lastRenderedGlyph < layoutManager!.numberOfGlyphs {
and
lastRenderedGlyph = NSMaxRange(layoutManager!.glyphRange(for: textContainer))
cz it is working much more slower.
So, what other improvements can I make? On iPhone 7 it takes like 7 seconds for initing, on iPhone 5s 20 secs +
Time profiler shows, that almost all the time is getting insertTextContainer function (addTextContainer).
Any suggestions?
Layout manager invalidates layout on addTextContainer
method call and rebuilds layout on textContainer(forGlyphAt:effectiveRange:)
. You can check it by setting delegate for layout manager and observing layoutManagerDidInvalidateLayout
. So rather then do layout once, you are doing it 500 times - once for every added text container.
You can add text containers in batches to reduce number of layouts, e.g.
var lastTextConainer: NSTextContainer? = nil
while nil == lastTextConainer {
for _ in 1...100 {
let textContainer = NSTextContainer(size: textContainerSize)
layoutManager.addTextContainer(textContainer)
}
lastTextConainer = layoutManager.textContainer(forGlyphAt: layoutManager.numberOfGlyphs - 1, effectiveRange: nil)
}
let pagesCount = layoutManager.textContainers.index(of: lastTextConainer!)! + 1
Empty text containers at the end you can leave or remove starting from last text container index. Enjoy!