如何在 iOS 的后台线程上绘制文本? [英] How do I draw text on a background thread in iOS?

查看:34
本文介绍了如何在 iOS 的后台线程上绘制文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在后台线程上绘制文本以将其保存为图像.

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 的后台线程上绘制文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆