Fix crash truncating a string of a node with a zero size

The crash happens in the placeholderImage of ASTextNode. The node is not visible in the time it try to get the `placeholderImage` and so the `visibleRange` has count 0 and a crash happens while accessing the first object of an empty array.
This commit is contained in:
Michael Schneider
2016-06-03 09:39:34 -07:00
parent 86deec4033
commit 19bb6519ed
8 changed files with 100 additions and 16 deletions

View File

@@ -59,7 +59,6 @@
NSAttributedString *truncationAttributedString = self.attributes.truncationAttributedString;
// get the index of the last character, so we can handle text in the truncation token
NSRange visibleRange = self.truncater.visibleRanges[0];
__block NSRange truncationTokenRange = { NSNotFound, 0 };
[truncationAttributedString enumerateAttribute:ASTextKitTruncationAttributeName inRange:NSMakeRange(0, truncationAttributedString.length)
@@ -75,6 +74,7 @@
truncationTokenRange = { 0, truncationAttributedString.length };
}
NSRange visibleRange = self.truncater.firstVisibleRange;
truncationTokenRange.location += NSMaxRange(visibleRange);
__block CGFloat minDistance = CGFLOAT_MAX;

View File

@@ -78,7 +78,7 @@
The character range from the original attributedString that is displayed by the renderer given the parameters in the
initializer.
*/
- (std::vector<NSRange>)visibleRanges;
@property (nonatomic, assign, readonly) std::vector<NSRange> visibleRanges;
/**
The number of lines shown in the string.
@@ -86,3 +86,13 @@
- (NSUInteger)lineCount;
@end
@interface ASTextKitRenderer (ASTextKitRendererConvenience)
/**
Returns the first visible range or an NSRange with location of NSNotFound and size of 0 if no first visible
range exists
*/
@property (nonatomic, assign, readonly) NSRange firstVisibleRange;
@end

View File

@@ -262,3 +262,17 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
}
@end
@implementation ASTextKitRenderer (ASTextKitRendererConvenience)
- (NSRange)firstVisibleRange
{
std::vector<NSRange> visibleRanges = self.visibleRanges;
if (visibleRanges.size() > 0) {
return visibleRanges[0];
}
return NSMakeRange(NSNotFound, 0);
}
@end

View File

@@ -20,7 +20,6 @@
NSCharacterSet *_avoidTailTruncationSet;
}
@synthesize visibleRanges = _visibleRanges;
@synthesize truncationStringRect = _truncationStringRect;
- (instancetype)initWithContext:(ASTextKitContext *)context
truncationAttributedString:(NSAttributedString *)truncationAttributedString
@@ -185,4 +184,14 @@
}];
}
- (NSRange)firstVisibleRange
{
std::vector<NSRange> visibleRanges = _visibleRanges;
if (visibleRanges.size() > 0) {
return visibleRanges[0];
}
return NSMakeRange(NSNotFound, 0);
}
@end

View File

@@ -14,10 +14,21 @@
#import "ASTextKitRenderer.h"
NS_ASSUME_NONNULL_BEGIN
@protocol ASTextKitTruncating <NSObject>
/**
The character range from the original attributedString that is displayed by the renderer given the parameters in the
initializer.
*/
@property (nonatomic, assign, readonly) std::vector<NSRange> visibleRanges;
@property (nonatomic, assign, readonly) CGRect truncationStringRect;
/**
Returns the first visible range or an NSRange with location of NSNotFound and size of 0 if no first visible
range exists
*/
@property (nonatomic, assign, readonly) NSRange firstVisibleRange;
/**
A truncater object is initialized with the full state of the text. It is a Single Responsibility Object that is
@@ -30,12 +41,14 @@
The truncater should not store a strong reference to the context to prevent retain cycles.
*/
- (instancetype)initWithContext:(ASTextKitContext *)context
truncationAttributedString:(NSAttributedString *)truncationAttributedString
avoidTailTruncationSet:(NSCharacterSet *)avoidTailTruncationSet;
truncationAttributedString:(NSAttributedString * _Nullable)truncationAttributedString
avoidTailTruncationSet:(NSCharacterSet * _Nullable)avoidTailTruncationSet;
/**
* Actually do the truncation.
Actually do the truncation.
*/
- (void)truncate;
@end
NS_ASSUME_NONNULL_END