Can NSLayoutManager be safely used on background thread?
Asked Answered
M

1

6

Even though the iOS doc says:

NLayoutManager, NSTextStorage, and NSTextContainer can be accessed from subthreads as long as the app guarantees the access from a single thread.

I encountered this exception occasionally:

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

Here is the backtrace:

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

One thing to notice is that my NLayoutManager is attached to a UITextView. You can think it as a normal UITextView that is used to do text layout in background thread.

So does it mean that contradicting what the doc says, NLayoutManager can not be safely used on a single background thread if it is attached to a UITextView?

Masson answered 1/5, 2014 at 2:50 Comment(1)
Did you found a solution for this? I'm running into the same problem at the moment. I want to use a cell in the background to recalculate the size.Besides
B
0

It seems to me that note in the docs actually explains the problem. Since you're using a layout manager attached to a UITextView, you can't guarantee it's being accessed from a single thread. It's best to assume that the text view could access the layout manager at any time, especially if the view is on screen. There's no way for you to know exactly how it's using the layout manager, but it's a safe bet that it's happening on the main thread.

You can have your background thread create a separate NSLayoutManager, NSTextStorage, and NSTextContainer, do all your layout calculations, and then apply those calculations on the main thread.

Bardo answered 3/8, 2014 at 0:35 Comment(2)
The UITextView is also created and only accessed in the same background thread.Masson
@Masson Generally, UIKit classes are not allowed to be used in non-main thread except some exceptional cases. So, I don't think you can create UITextView instance safely in background thread.Insupportable

© 2022 - 2024 — McMap. All rights reserved.