我收到以下错误:
我的代码似乎无法解决问题。这是我的AHInstagramImageData
中的一些代码-(id)initWithData:(NSDictionary *)data
{
self = [super init];
if (!self) {
return nil;
}
for (NSDictionary * comment in imgCmt){
AHInstagramImageComment * instagramImgComment = [[AHInstagramImageComment alloc] initWithData:comment];
[comments insertObject:instagramImgComment atIndex:0];
[instagramImgComment release];
}
}
and then on the AHInstagramImageComment I have:
-(id)initWithData:(NSDictionary *)data
{
self = [super init];
if (!self) {
return nil;
}
[self calculateCommentsHeight];
return self;
}
- (void) calculateCommentsHeight
{
NSString *combinedComment = [NSString stringWithFormat:@"%@ %@", self.username, self.text];
CGFloat desiredHeight = [combinedComment sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:14] constrainedToSize:CGSizeMake(kCommentsMaxWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeClip].height;
if (desiredHeight >= 50){
commentHeight_ = desiredHeight;
} else {
commentHeight_ = 50;
}
commentHeight_ += kTimestampMaxHeight;
commentHeight_ += 5;
}
所以我必须在后台队列中初始化AHInstagramImageData:
[weakSelf.backgroundQueue_ addOperationWithBlock:^{
NSArray *arr = [response valueForKey:@"data"];
int startingIndex = [[AHImageDataSource sharedDataSource] count];
for (NSDictionary * data in arr){
AHInstagramImageData * imgData = [[AHInstagramImageData alloc] initWithData:data];
} }];
这些都有错吗?
答案 0 :(得分:4)
核心文本有点线程安全,如下所述:Alternative for sizeWithFont: method
使用CoreText,我编写了一个包装CTFramesetterSuggestFrameSizeWithConstraints的NSString类,并且是线程安全的。可能对找到这篇文章并想要不同解决方案的人有用。这个兼容iOS 5和iOS 6,但出于某种原因在iOS 6上提供了更好的结果。
它为您返回一个建议的CGSize,但也会告诉您它能够适应多少字符大小,并采用约束。
NSString + SizeCalculation.h
@interface NSString (SizeCalculation)
// Uses CoreText instead of UIStringDrawing, since UIStringDrawing is not thread safe
- (CGSize) sizeWithFontName:(NSString*)fontName constraints:(CGSize)constraint targetSize:(CGFloat)target minimumSize:(CGFloat)minimum optimalFontSize:(CGFloat*)optimal fitRange:(NSRange*)range;
@end
的NSString + SizeCalculation.m
#import <CoreText/CoreText.h>
@implementation NSString (SizeCalculation)
- (CGSize) sizeWithFontName:(NSString*)fontName constraints:(CGSize)constraint targetSize:(CGFloat)target minimumSize:(CGFloat)minimum optimalFontSize:(CGFloat*)optimal fitRange:(NSRange*)range
{
CFRange fitRange;
CGSize suggestion;
do {
id font = (__bridge_transfer id) CTFontCreateWithName((__bridge CFStringRef) fontName, target, NULL);
NSAttributedString *string = [[NSAttributedString alloc] initWithString:self attributes:@{(id)kCTFontAttributeName:font}];
id framesetter = (__bridge_transfer id) CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) string);
suggestion = CTFramesetterSuggestFrameSizeWithConstraints((__bridge CTFramesetterRef)(framesetter), CFRangeMake(0, self.length), nil, constraint, &fitRange);
} while (fitRange.length < self.length && target > minimum && (target -= 2.0f));
if (optimal != NULL) *optimal = target;
if (range != NULL) *range = NSMakeRange(fitRange.location,fitRange.length);
return suggestion;
}
@end
你这样使用它。
CGFloat fontSize = 24.0f;
NSRange range;
NSString *title = @"Hello World";
CGSize suggestedSize = [title sizeWithFontName:@"HelveticaNeue-Bold" constraints:CGSizeMake(200.0f,35.0f) targetSize:fontSize minimumSize:16.0f optimalFontSize:&fontSize fitRange:&range];
suggestedSize 然后包含一个适合标题的CGSize fontSize 。此外, range 会告诉您在达到最小尺寸之前能够容纳多少个字符。如果您不关心,可以将NULL传递到最佳大小和适合范围。
P.S。我尝试重新使用CoreText部分,但它没有工作,所以需要重新初始化,但它仍然非常快,因为你在后台线程上运行它会很好。
P.p.s如果您只需要获得单行文本的高度,我就会编写一个具有更好性能的类似方法。 https://gist.github.com/duedal/4742069
答案 1 :(得分:3)
之前我遇到过类似的问题。目前存在一个错误,导致[NSString sizeWithFont:]
和[NSString drawInRect:]
无法在后台线程上运行,或通过NSOperations
运行。
查看此链接: Bug in UIKit string drawing method?
您有几个选择:
sizeWithFont:
与NSOperations
一起使用。将NSOperationQueue
的最大操作次数设置为1:
[queue setMaxConcurrentOperations:1];
使用核心文字和NSAttributedStrings
,它们有自己的“sizeWithFont
”方法:CTFramesetterSuggestFrameSizeWithConstraints
[NSOperationQueue mainQueue];
在主线程上运行操作。答案 2 :(得分:0)
WebCore / WebKit不是完全线程安全的,必须在主线程上运行。问题是,字体和字符串操作使用WebKit。
在主线程上调用你的字符串绘图(包括调整大小)代码,崩溃应该停止。