我需要在后台线程上绘制文本以将其保存为图像。
我正在做
UIGraphicsPushContext()
[NSString drawInRect:]
UIGraphicsPopContext()
代码工作正常,但有时当我同时在主线程上绘图时,它会在drawInRect中崩溃。
我尝试使用NSAttributedString,如下所示: UIStringDrawing methods don't seem to be thread safe in iOS 6。但是[NSAttributedString drawInRect:]似乎不会出于某种原因在我的后台线程上呈现任何内容。主线程似乎工作正常。
我一直在考虑使用Core Text,但看起来Core Text也有类似的问题:CoreText crashes when run in multiple threads
是否有线程安全的方式来绘制文本?
更新 如果我运行此代码,它几乎会立即在drawInRect中与EXC_BAD_ACCESS崩溃:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
UIFont* font = [UIFont systemFontOfSize:14.0f];
for (int i = 0; i < 100000000; i++) {
[@"hello" drawInRect:CGRectMake(0, 0, 100, 100) withFont:font];
}
UIGraphicsEndImageContext();
});
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
UIFont* font = [UIFont systemFontOfSize:12.0f];
for (int i = 0; i < 100000000; i++) {
[@"hello" drawInRect:CGRectMake(0, 0, 100, 100) withFont:font];
}
UIGraphicsEndImageContext();
如果我删除UIFont并且只绘制没有字体的文本,它可以正常工作。
更新 这似乎只在iOS 6.1上崩溃,但似乎在iOS 7.1上运行良好。
答案 0 :(得分:6)
由于iOS6(可能更早)你可以在不同的线程上使用这些方法,只要你在同一个线程上使用UIGraphicsBeginImageContext ...创建了一个新的上下文。
drawRect:方法默认为他们自己的线程的当前上下文。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
UIFont* font = [UIFont systemFontOfSize:26];
NSString* string = @"hello";
NSAttributedString* attributedString = [[NSAttributedString alloc] initWithString:string attributes:@{NSFontAttributeName:font}];
[attributedString drawInRect:CGRectMake(0, 0, 100, 100)];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[UIImagePNGRepresentation(image) writeToFile:@"/testImage.png" atomically:YES];
});
在模拟器上运行它,它会将结果输出到硬盘的根目录。
答案 1 :(得分:0)
根据Apple's NSString UIKit Additions Reference,[NSString drawInRect:...]
是从应用的主要线程调用 必须 的方法之一(查看“概述” “该文件的一部分)。它说:
此类扩展中描述的方法必须在您的 应用程序的主要线程。
然后,任何更新UI 的内容都总是在主线程上......当然有些东西可能会出现在后台线程上(例如包括字符串和图像绘制 - { {3}})。
最后,see this related question and answers(other people have reported problems trying to draw on background threads using "UIGraphicsPushContext
"),因此iOS 6仍然存在问题。