可以在后台线程上安全地使用NSLayoutManager吗?

an0*_*an0 5 nslayoutmanager ios textkit

即使iOS文档说:

只要应用程序保证从单个线程访问,就可以从子线程访问NLayoutManager,NSTextStorage和NSTextContainer.

我偶尔遇到这个例外:

由于未捕获的异常'NSInternalInconsistencyException'终止应用程序,原因:'只在主线程上运行!'

这是回溯:

Exception Type:  SIGABRT
Exception Codes: #0 at 0x197bca58c
Crashed Thread:  7

Application Specific Information:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'

Last Exception Backtrace:
0   CoreFoundation                       0x000000018afd2f50 __exceptionPreprocess + 132
1   libobjc.A.dylib                      0x00000001974dc1fc objc_exception_throw + 56
2   CoreFoundation                       0x000000018afd2e10 +[NSException raise:format:arguments:] + 112
3   Foundation                           0x000000018bb0ae20 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 84
4   UIFoundation                         0x00000001940f0654 -[NSLayoutManager(NSPrivate) _resizeTextViewForTextContainer:] + 412
5   UIFoundation                         0x00000001940f0318 -[NSLayoutManager(NSPrivate) _recalculateUsageForTextContainerAtIndex:] + 1748
6   UIFoundation                         0x000000019411ec2c _enableTextViewResizing + 236
7   UIFoundation                         0x0000000194123e18 -[NSLayoutManager textContainerForGlyphAtIndex:effectiveRange:] + 484
8   UIFoundation                         0x0000000194125c60 -[NSLayoutManager glyphRangeForTextContainer:] + 352
Run Code Online (Sandbox Code Playgroud)

有一点需要注意的是,我NLayoutManager是附属于一个UITextView.您可以将其视为UITextView用于在后台线程中进行文本布局的常规.

那么它是否意味着与文档所说的相矛盾,NLayoutManager如果将它附加到一个后台线程上,就不能安全地在单个后台线程上使用UITextView

rob*_*cer 0

在我看来,文档中的注释实际上解释了这个问题。由于您使用的是附加到 a 的布局管理器UITextView,因此您不能保证它是从单个线程访问的。最好假设文本视图可以随时访问布局管理器,特别是当视图位于屏幕上时。您无法确切地知道它是如何使用布局管理器的,但可以肯定它发生在主线程上。

您可以让后台线程创建单独的NSLayoutManagerNSTextStorage、 和NSTextContainer,执行所有布局计算,然后在主线程上应用这些计算。

  • @an0 一般来说,除了一些特殊情况外,UIKit 类不允许在非主线程中使用。因此,我认为您无法在后台线程中安全地创建“UITextView”实例。 (3认同)