mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-02-19 01:06:30 +00:00
[ASTextKitComponents] Make sure Main Thread Checker isn't triggered during background calculations #trivial (#612)
* Add unit test * Make sure TextKit components can calculate size in background without upsetting Main Thread Checker - Add a new thread-safe text view bounds. - Temporary components stack doesn't have a text view so it can be safely deallocated off main. * Add ASTextKitComponentsTextView * Remove unnecessary change * Fix minor mistake * ASTextKitComponentsTextView has only 1 initializer * Minor change * Switch to atomic property * Remove manual synthesization
This commit is contained in:
@@ -20,6 +20,37 @@
|
||||
|
||||
#import <tgmath.h>
|
||||
|
||||
@interface ASTextKitComponentsTextView ()
|
||||
@property (atomic, assign) CGRect threadSafeBounds;
|
||||
@end
|
||||
|
||||
@implementation ASTextKitComponentsTextView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer
|
||||
{
|
||||
self = [super initWithFrame:frame textContainer:textContainer];
|
||||
if (self) {
|
||||
_threadSafeBounds = self.bounds;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setFrame:(CGRect)frame
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[super setFrame:frame];
|
||||
self.threadSafeBounds = self.bounds;
|
||||
}
|
||||
|
||||
- (void)setBounds:(CGRect)bounds
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[super setBounds:bounds];
|
||||
self.threadSafeBounds = bounds;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ASTextKitComponents ()
|
||||
|
||||
// read-write redeclarations
|
||||
@@ -27,9 +58,6 @@
|
||||
@property (nonatomic, strong, readwrite) NSTextContainer *textContainer;
|
||||
@property (nonatomic, strong, readwrite) NSLayoutManager *layoutManager;
|
||||
|
||||
// Indicates whether or not this object must be deallocated on main thread. Defaults to YES.
|
||||
@property (nonatomic, assign) BOOL requiresMainThreadDeallocation;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASTextKitComponents
|
||||
@@ -61,8 +89,6 @@
|
||||
components.textContainer.lineFragmentPadding = 0.0; // We want the text laid out up to the very edges of the text-view.
|
||||
[components.layoutManager addTextContainer:components.textContainer];
|
||||
|
||||
components.requiresMainThreadDeallocation = YES;
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
@@ -70,11 +96,9 @@
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_requiresMainThreadDeallocation) {
|
||||
ASDisplayNodeAssertMainThread();
|
||||
}
|
||||
// Nil out all delegates to prevent crash
|
||||
if (_textView) {
|
||||
ASDisplayNodeAssertMainThread();
|
||||
_textView.delegate = nil;
|
||||
}
|
||||
_layoutManager.delegate = nil;
|
||||
@@ -88,10 +112,8 @@
|
||||
|
||||
// If our text-view's width is already the constrained width, we can use our existing TextKit stack for this sizing calculation.
|
||||
// Otherwise, we create a temporary stack to size for `constrainedWidth`.
|
||||
if (CGRectGetWidth(components.textView.bounds) != constrainedWidth) {
|
||||
if (CGRectGetWidth(components.textView.threadSafeBounds) != constrainedWidth) {
|
||||
components = [ASTextKitComponents componentsWithAttributedSeedString:components.textStorage textContainerSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX)];
|
||||
// The temporary stack can be deallocated off main
|
||||
components.requiresMainThreadDeallocation = NO;
|
||||
}
|
||||
|
||||
// Force glyph generation and layout, which may not have happened yet (and isn't triggered by -usedRectForTextContainer:).
|
||||
@@ -112,9 +134,7 @@
|
||||
|
||||
// Always use temporary stack in case of threading issues
|
||||
components = [ASTextKitComponents componentsWithAttributedSeedString:components.textStorage textContainerSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX)];
|
||||
// The temporary stack can be deallocated off main
|
||||
components.requiresMainThreadDeallocation = NO;
|
||||
|
||||
|
||||
// Force glyph generation and layout, which may not have happened yet (and isn't triggered by - usedRectForTextContainer:).
|
||||
[components.layoutManager ensureLayoutForTextContainer:components.textContainer];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user