0

我想在屏幕上显示我从互联网上获取的图像。我已经使用 NSURLConnection 创建了一个异步调用来获取数据,并且在响应块中,我调用了代码以将其分配给 UIImage 对象。

我的问题是为什么我需要在块执行后调用 sleep(1) ?如果我不调用它,那么我的图像不会绘制在屏幕上。这是实现这一目标的另一种更优雅的方式吗?

-(void)loadImage:(NSString *)url
{
    NSURL *imageURL = [NSURL URLWithString:url];
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0f];
    [NSURLConnection sendAsynchronousRequest:imageRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if(!connectionError) {
            if(data) {
                //there goes the main thingy
                self.myView.wallpaperImage  = [UIImage imageWithData:data];
                [self.myView setNeedsDisplay];
            } else {
                NSLog(@"No data found at url:%@",url);
            }
        } else {
            NSLog(@"Could not connect to %@",url);
        }
    }];
    sleep(1);
}
4

1 回答 1

2

这个:

self.myView.wallpaperImage  = [UIImage imageWithData:data];
[self.myView setNeedsDisplay];

发生在由传递给 sendAsynchronousRequest 的 NSOperationQueue 管理的线程上。这些方法需要从主线程调用。您的睡眠可能会导致主线程的运行循环进行迭代,之后这些调用似乎已经起作用。要解决此问题并避免当前方法可能遇到的一大堆其他问题,请执行以下操作:

    [NSURLConnection sendAsynchronousRequest:imageRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if([data length] > 0) {
            //there goes the main thingy
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.myView.wallpaperImage  = [UIImage imageWithData:data];
                [self.myView setNeedsDisplay];
            }];
        } else {
            // Perform your error handling here.

        }
    }];

这将用于[NSOperationQueue mainQueue]从主队列执行那些 UIKit 调用 - 而不是 libdispatch。libdispatch 是一个低级接口,推荐的最佳实践是始终首选更高级别的接口 - 在本例中为 NSOperationQueue。UIKit 仅在从主线程(或队列)调用时才是安全的。它还会更改您的错误处理行为以遵循平台的最佳实践- 检查您的调用结果(在本例中为数据),然后处理返回的任何错误。

您的代码实际上是块保留捕获对象(在本例中为 self)的一个很好的例子。如果这里没有保留循环,ARC 可能会queue在它超出范围时立即销毁,并且该块永远不会执行。相反,由于保留周期,队列一直存在,直到块执行。

于 2014-06-18T23:19:29.077 回答