iOS:为什么我需要在NSURLConnection sendAsynchronousRequest之后使用sleep(1)?

时间:2014-06-18 22:30:41

标签: ios objective-c uiimage nsurlconnection setneedsdisplay

我想在屏幕上显示我从互联网上拍摄的图像。我用过 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);
}

1 个答案:

答案 0 :(得分:2)

此:

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

发生在由传递给sendAsynchronousRequest的NSOperationQueue管理的线程上。需要从主线程调用这些方法。 你的睡眠可能导致主线程的runloop迭代,之后这些调用似乎有效。 要解决这个问题,并避免当前的方法会遇到大量其他问题,请执行以下操作:

    [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才是安全的。 它还会更改您的错误处理行为,以跟随bestpractices platform - 检查您的调用结果(在本例中为数据),然后处理返回的任何错误。

您的代码实际上是块保留捕获对象(在本例中为self)的原因的一个很好的示例。如果此处没有保留周期,ARC可能会在超出范围时立即销毁queue,并且块将永远不会执行。相反,由于保留周期,队列保持不变,直到块执行完毕。