并发绘图

原帖:http://objccn.io/issue-3-1/

我们除了在主队列中可以向 CALayer 的后备存储中绘制一些东西,其他方法都将不可行。可怕的事情将会发生。我们能做的就是向一个完全断开链接的位图上下文中进行绘制。

正如我们上面所提到的一样,在 Core Graphics 下,所有 Core Graphics 绘制方法都需要一个上下文参数来指定绘制到那个上下文中。UIKit 有一个当前上下文的概念(也就是绘制到哪儿去)。这个当前的上下文就是 per-thread.

为了同时绘制,我们需要做下面的操作。我们需要在另一个队列创建一个图像,一旦我们拥有了图像,我们可以切换回主队列,并且设置这个图像为 UIImageView 的图像

增加一个你可以在其中绘制的新方法:

- (UIImage *)renderInImageOfSize:(CGSize)size
{
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);

    // do drawing here

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

这个方法通过 UIGraphicsBeginImageContextWithOptions() 方法,并根据给定的大小创建一个新的 CGContextRef 位图。这个方法也会将这个上下文设置为当前UIKit的上下文。现在你可以在这里做你想在 -drawRect: 中做的事了。然后我们可以通过UIGraphicsGetImageFromCurrentImageContext(),将获得的这个上下文位图数据作为一个 UIImage,最终移除这个上下文。

很重要的一点就是,你在这个方法中所做的所有绘图的代码都是线程安全的,也就是说,当你访问属性等等,他们需要线程安全。因为你是在另一个队列中调用这个方法的。如果这个方法在你的视图类中,那就需要注意一点了。另一个选择就是创建一个单独的渲染类,并设置所有需要的属性,然后通过触发来渲染图片。如果这样,你可以通过使用简单的 UIImageView 或者 UITableViewCell。

要知道,所有 UIKit 的绘制 API 在使用另一个队列时,都是安全的。只需要确定是在同一个操作中调用他们的,这个操作需要以UIGraphicsBeginImageContextWithOptions() 开始,以 UIGraphicsEndIamgeContext() 结束。

你需要像下面这样触发渲染代码:

UIImageView *view; // assume we have this
NSOperationQueue *renderQueue; // assume we have this
CGSize size = view.bounds.size;
[renderQueue addOperationWithBlock:^(){
        UIImage *image = [renderer renderInImageOfSize:size];
        [[NSOperationQueue mainQueue] addOperationWithBlock:^(){
            view.image = image;
        }];
}];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值