在drawRect中使用GCD /异步代码:

时间:2011-03-30 13:26:09

标签: iphone cocoa-touch

我正在尝试从drawRect:内的网址加载图片。我们的图像加载代码是一个如下所示的方法:- (void) loadImage:(NSURL*)url done:(void(^)(UIImage*))done;,它创建一个异步NSURLConnection并回调图像。

所以,drawRect:中的代码如下所示:

CGContextRef context = UIGraphicsGetCurrentContext()
[service loadImage:url done:^(UIImage * image){
    CGContextDrawImage(context, frame, image.CGImage);
}];

不幸的是,这不起作用。永远不会画出图像。

我也尝试过使用同步连接([NSData dataWithContentsOfUrl:]),但它会阻塞线程并减少不必要的速度。我不想使用UIImageView。

这样做的正确方法是什么?谢谢!

4 个答案:

答案 0 :(得分:3)

我认为正确的方法是预先加载图像,或者在收到图像时通过调用“setNeedsDisplayInRect:”或者在单独的方法中进行自己的绘图处理来绘制图像(iOS可能会阻止您做这虽然,我不确定)。显然,setNeedsDisplayInRect变体需要你手头的图像第二次绘制(缓存它)。

如果您异步加载图像,您的drawRect方法可能会在加载图像之前退出并且绘图焦点不再锁定在drawRect上,因此无法在上下文中绘制图像。您是否尝试设置断点来验证这一点?关于锁定我可能是错的,但我认为我在某些时候读过类似的内容。

答案 1 :(得分:3)

仔细思考 - 为什么运行?在输入块时,无法保证context仍然是当前上下文(或者甚至它的后备存储仍然完全有效)。通过使用异步回调,无论是块还是委托方法或其他方法,您都有意将代码推迟到以后的某个时间点。对-drawRect:的调用已经结束,并且在您输入块之前很久就不在堆栈中了。

答案 2 :(得分:0)

我要尝试的第一件事是确保异步处理程序在主线程上运行:

[service loadImage:url done:^(UIImage * image) {
    dispatch_async(dispatch_get_main_queue(), ^{
        CGContextDrawImage(context, frame, image.CGImage);
    });
}];

如果这没有帮助,我会开始怀疑上下文是否仍然有效。指针是,但上下文可能不是。也许您可以将上下文获取移动到处理程序:

[service loadImage:url done:^(UIImage * image) {
    dispatch_async(dispatch_get_main_queue(), ^{
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextDrawImage(context, frame, image.CGImage);
        …
    });
}];

不确定API是否合理,我不做这样的事情。

答案 3 :(得分:0)

你试过了吗?

__block CGContextRef context = UIGraphicsGetCurrentContext()
[service loadImage:url done:^(UIImage * image){
    CGContextDrawImage(context, frame, image.CGImage);
}];

您可能必须对框架执行相同的操作,因此当块返回时,它知道应修改的上下文和框架。