sizeWithFont 不是线程安全。

 在ios开发中经常使用用sizeWithFont 方法来计算UILabel 的frame, 例如动态计算UITableViewCell 的高度,在主线程处理没有问题,但是在子线程用此方法来计算就会出现Crash,因为 UIStringDrawing 中的方法不是线程安全的。以下代码在ios6 模拟器中测试过:

dispatch_queue_t queue = dispatch_queue_create("com.queue", NULL);

for (int i = 0; i < 10000; i++) {

    dispatch_async(queue, ^{

        NSString *string = @"My string";
        CGSize size = [string sizeWithFont:[UIFont boldSystemFontOfSize:13]];
    });
}

for (int i = 0; i < 10000; i++) {

    NSString *string = @"My string";
    CGSize size = [string sizeWithFont:[UIFont boldSystemFontOfSize:13]];
}

dispatch_release(queue);

错误代码:

WebCore`WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>):
。。。
0x2b635d8:  jne    0x2b635f1                 ; WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>) + 65
0x2b635da:  calll  0x2b5b740                 ; WebCore::fontCache()
。。。
0x2b635ec:  calll  0x2b5c210                 ; WebCore::FontCache::releaseFontData(WebCore::SimpleFontData const*)
0x2b635f1:  incl   %ebx
。。。0x2b63620:  calll  0x364281a                 ; symbol stub for: WTF::fastFree(void*)
0x2b63625:  movl   $0, 4(%ebx)
。。。0x2b63674:  je     0x2b63696                 ; WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>) + 230
。。。
0x2b6367f:  je     0x2b63686                 ; WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>) + 214
0x2b63681:  decl   %ecx
0x2b63682:  movl   %ecx, (%eax)
0x2b63684:  jmp    0x2b63693                 ; WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>) + 227
0x2b63686:  addl   $-4, %eax
0x2b63689:  je     0x2b63693                 ; WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>) + 227
0x2b6368b:  movl   (%eax), %ecx
。。。
0x2b63698:  testl  %ecx, %ecx
0x2b6369a:  je     0x2b636a4                 ; WebCore::FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector>) + 244
0x2b6369c:  movl   (%ecx), %eax
。。。
0x2b636a7:  calll  0x2b5b740                 ; WebCore::fontCache()
0x2b636ac:  movl   %eax, (%esp)
0x2b636af:  calll  0x2b5cce0                 ; WebCore::FontCache::generation()
。。。
0x2b636bf:  ret    

所以,建议使用UIStringDrawing放在主线程中使用。

stackoverflow上也有其他计算方法,本人没试过。

参考:

http://stackoverflow.com/questions/12744558/uistringdrawing-methods-dont-seem-to-be-thread-safe-in-ios-6

原文地址:https://www.cnblogs.com/zeejun/p/3261117.html