我有一个带有长文本的NSTextStorage(例如一本书中有500页,而在当前字体的设备上有9000多页)。我通过以下方式为textcontainer分发了此文本:

let textStorageLength = defaultTextStorage?.length ?? 0
while layoutManager!.textContainer(forGlyphAt: textStorageLength - 1,
                                   effectiveRange: nil) == nil {
  let textContainer = NSTextContainer(size: textContainerSize)
  layoutManager!.addTextContainer(textContainer)
  pagesCount += 1
}

问题是,它需要很长的时间来初始化所有这些容器等。我已经做了一些改进,例如从使用中更改代码
while lastRenderedGlyph < layoutManager!.numberOfGlyphs {

lastRenderedGlyph = NSMaxRange(layoutManager!.glyphRange(for: textContainer))
cz它的工作要慢得多。

因此,我可以对做哪些其他改进?在iPhone 7上,启动大约需要7秒,在iPhone 5s上,启动需要20秒+

时间分析器显示,几乎所有时间都在获取insertTextContainer函数(addTextContainer)。

有什么建议?

最佳答案

布局管理器使addTextContainer方法调用上的布局无效,并重建textContainer(forGlyphAt:effectiveRange:)上的布局。您可以通过设置布局管理器的委托并观察layoutManagerDidInvalidateLayout来检查它。因此,而不是进行一次布局,您要做500次-对于每个添加的文本容器一次。

您可以批量添加文本容器以减少布局数量,例如

  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

最后,您可以从上一个文本容器索引开始保留或删除空的文本容器。请享用!

07-24 09:44
查看更多