问题描述
我需要在后台线程上绘制文本以将其保存为图像.
I need to draw text on a background thread to save it as an image.
我在做
UIGraphicsPushContext()
[NSString drawInRect:]
UIGraphicsPopContext()
代码工作正常,但有时当我同时在主线程上绘图时它会在 drawInRect 中崩溃.
The code works fine, but sometimes it crashes in drawInRect when I'm also drawing on the main thread at the same time.
我尝试按照此处的建议使用 NSAttributedString:UIStringDrawing 方法似乎没有在 iOS 6 中是线程安全的.但是 [NSAttributedString drawInRect:] 由于某种原因似乎没有在我的后台线程上呈现任何内容.不过,主线程似乎工作正常.
I tried to use NSAttributedString as suggested here:UIStringDrawing methods don't seem to be thread safe in iOS 6. But [NSAttributedString drawInRect:] doesn't seem to render anything on my background thread for some reason. Main thread seems to work fine though.
我一直在考虑使用 Core Text,但看起来 Core Text 也有类似的问题:CoreText 在多线程中运行时崩溃
I've been thinking of using Core Text, but looks like Core Text also has similar problem: CoreText crashes when run in multiple threads
是否有线程安全的方式来绘制文本?
Is there a thread safe way to draw text?
更新:如果我运行此代码,它几乎立即在带有 EXC_BAD_ACCESS 的 drawInRect 中崩溃:
UPDATE:If I run this code, it almost immediately crashes in drawInRect with 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 并只绘制没有字体的文本,它就可以正常工作.
If I remove UIFont and just draw text without font it works fine.
更新:这似乎只会在 iOS 6.1 上崩溃,但在 iOS 7.1 上似乎可以正常工作.
UPDATE:This only seems to crash on iOS 6.1, but seems to work fine on iOS 7.1.
推荐答案
从 iOS6(可能更早版本)开始,你可以在不同的线程上使用这些方法,只要你使用 UIGraphicsBeginImageContext... 创建了一个新的上下文同一个线程.
Since iOS6 (might have been earlier) you can use those methods on a different thread, as long as you have created a new context using UIGraphicsBeginImageContext... on that same thread.
drawRect: 方法默认为自己线程的当前上下文.
The drawRect: method defaults to the current context of their own thread.
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];
});
在模拟器上运行,它会将结果输出到您硬盘的根目录.
Run that on the simulator and it will output the result to the root directory of your hard drive.
这篇关于如何在 iOS 的后台线程上绘制文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!