您的位置:首页 > 移动开发

NSAttributedString initWithData 阻塞App问题

2016-04-12 15:59 423 查看
最近调试App的时候,发现App莫名的阻塞在

NSAttributedString *hintAttributedString = [[NSAttributedString alloc] initWithData:[discountDesc dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}  documentAttributes:nil error:nil];
这段方法,这是系统的API怎么会阻塞App呢?

然后网上搜索了下,发现这样一段话:

Multicore considerations: Since OS X v10.4, NSAttributedString has used WebKit for all import (but not for export)
of HTML documents. Because WebKit document loading is not thread safe, this has not been safe to use on background threads. For applications linked on OS X v10.5 and later, if NSAttributedString imports HTML documents on any but the main thread, the use of
WebKit is transferred to the main thread via performSelectorOnMainThread:withObject:waitUntilDone:. This makes the operation thread safe, but it requires that the main thread be executing the run loop in one of the common modes. This behavior can be overridden
by setting the value of the standard user default NSRunWebKitOnAppKitThread to either YES (to obtain the new behavior regardless of linkage) or NO (to obtain the old behavior regardless of linkage).

然后调试发现NSAttributedString的initWithData是个非常耗时的操作,由此猜想将创建NSAttributedString的代码放到子线程中实现,然后回到主线程中更新UI,然后一切就都完美了。

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *discountDesc = _reservationModel.promotionModel.discount_fee_desc;
NSAttributedString *hintAttributedString = [[NSAttributedString alloc] initWithData:[discountDesc dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];dispatch_async(dispatch_get_main_queue(), ^{
_promotionLabel.attributedText = hintAttributedString;
_promotionLabel.numberOfLines = 0;
_promotionLabel.font = [UIFont systemFontOfSize:14];
_promotionLabel.textAlignment = NSTextAlignmentCenter;
});
});
经过测试返现 NSAttributedString 的初始化在iOS8.3以下不能放在放在子线程里初始化,否则App会崩溃,而在iOS8.3及以上是可以放在子线程中初始化,然后回到主线程刷新UI的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: