是否可以使用Quartz 2D在另一个线程上创建UIImage?

时间:2012-02-05 17:35:30

标签: ios ios5 grand-central-dispatch quartz-2d

我想移动一些需要几秒钟才能在另一个线程上生成UIImage的代码,但是在使用时会出现上下文错误

    UIGraphicsBeginImageContextWithOptions(size,false,0);

在调用dispatch之前为我尝试的每个操作生成一个说“无效上下文0x0”的图像。这是可能吗?

3 个答案:

答案 0 :(得分:13)

What's New in iOS: iOS 4.0说:

  
      
  • 在UIKit中绘制到图形上下文现在是线程安全的。特别:   
        
    • 用于访问和操作图形上下文的例程现在可以正确处理驻留在不同线程上的上下文。
    •   
    • 字符串和图像绘制现在是线程安全的。
    •   
    • 现在可以安全地使用多个线程中的颜色和字体对象。
    •   
  •   

听起来你尝试过这样的事情:

UIGraphicsBeginImageContextWithOptions(size,false,0);
dispatch_async(someQueue, ^{
    [UIColor.whiteColor setFill];
    UIRectFill(0, 0, 20, 20);
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        self.imageView.image = image;
    });
};

这不起作用,因为每个线程都有自己的图形上下文堆栈(从iOS 4.0开始)。你需要这样做:

dispatch_async(someQueue, ^{
    UIGraphicsBeginImageContextWithOptions(size,false,0);
    [UIColor.whiteColor setFill];
    UIRectFill(0, 0, 20, 20);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageView.image = image;
    });
};

更新

UIGraphicsBeginImageContextWithOptions和其他UIKit图形功能documentation现在说

  

在iOS 4及更高版本中,您可以从应用的任何主题调用此功能。

UIColor的{​​{3}}说

  

颜色对象是不可变的,因此可以安全地从应用程序中的多个线程中使用它们。

UIFont的{​​{3}}说

  

字体对象是不可变的,因此可以安全地在应用程序中的多个线程中使用它们。

然而,UIKit NSString的{​​{3}} - 绘图添加内容

  

必须在应用程序的主线程中使用此类扩展中描述的方法。

所以你必须从后台主题尝试类似[@"hello" drawAtPoint:CGPointZero withAttributes:attrs]的内容。

答案 1 :(得分:1)

docs说:

  

您应该只从应用程序的主线程调用此函数。

所以在另一个线程上调用它不是一个好主意。

您可以尝试使用CoreGraphics,然后调用CGBitmapContextCreate()

答案 2 :(得分:0)

您可以使用CGContext轻松操作,以便在辅助线程上生成CGImage

返回主线程,从UIImage创建CGImage。请注意UIImage是一个不可变的容器类型 - 这不应该导致图像数据的深层副本。