Skip to content

Commit

Permalink
[ASTextKitComponents] Temporary components can be deallocated off main
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenhuy committed Oct 10, 2017
1 parent 4dbb644 commit 1ccb858
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Source/TextKit/ASTextKitComponents.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ AS_SUBCLASSING_RESTRICTED
@property (nonatomic, strong, readonly) NSTextStorage *textStorage;
@property (nonatomic, strong, readonly) NSTextContainer *textContainer;
@property (nonatomic, strong, readonly) NSLayoutManager *layoutManager;
@property (nullable, nonatomic, strong) UITextView *textView;
@property (nonatomic, strong, nullable) UITextView *textView;

@end

Expand Down
20 changes: 16 additions & 4 deletions Source/TextKit/ASTextKitComponents.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ @interface ASTextKitComponents ()
@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
Expand Down Expand Up @@ -58,17 +61,22 @@ + (instancetype)componentsWithTextStorage:(NSTextStorage *)textStorage
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;
}

#pragma mark - Lifecycle

- (void)dealloc
{
ASDisplayNodeAssertMainThread();

// Nil out all delegate to prevent crash
_textView.delegate = nil;
if (_requiresMainThreadDeallocation) {
ASDisplayNodeAssertMainThread();
}
// Nil out all delegates to prevent crash
if (_textView) {
_textView.delegate = nil;
}
_layoutManager.delegate = nil;
}

Expand All @@ -82,6 +90,8 @@ - (CGSize)sizeForConstrainedWidth:(CGFloat)constrainedWidth
// Otherwise, we create a temporary stack to size for `constrainedWidth`.
if (CGRectGetWidth(components.textView.bounds) != 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:).
Expand All @@ -102,6 +112,8 @@ - (CGSize)sizeForConstrainedWidth:(CGFloat)constrainedWidth

// 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];
Expand Down

0 comments on commit 1ccb858

Please sign in to comment.