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

标签 ios objective-c uiimage nsurlconnection setneedsdisplay

我想在屏幕上显示我从互联网上获取的图像。我用过 NSURLConnection 创建异步调用以获取数据,在响应 block 中,我调用代码将其分配给 UIImage 对象。

我的问题是为什么我需要在 block 执行后调用 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);
}

最佳答案

这个:

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

发生在由传递给 sendAsynchronousRequest 的 NSOperationQueue 管理的线程上。这些方法需要从主线程调用。 您的 sleep 可能导致主线程的 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 是一个低级接口(interface),推荐的最佳做法是始终首选更高级别的接口(interface)——在本例中为 NSOperationQueue。 UIKit 只有在从主线程(或队列)调用时才是安全的。 它还会更改您的错误处理行为以遵循 best practices对于 platform - 检查您的调用结果(在本例中为数据),然后处理返回的任何错误。

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

关于iOS:为什么我需要在 NSURLConnection sendAsynchronousRequest 之后使用 sleep(1)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24296038/

相关文章:

ios - 在客户端应用程序商店上传应用程序并与 .p12 和 .mobileprovision 连接

iphone - 在 Core Data 的后台线程上使用获取请求

ios - 在 SWIFT 2 中使用来自 cocoapod 的 mailcore2

ios - 无法更改 UIImageView 图像

swift - 更改 UINavigationBar 按钮图像

ios - 合并并编辑2个UIImage

iOS 表格 View - 在单元格或标签上设置标签?

ios - 'NSInternalInconsistencyException',原因 : 'Could not load NIB in bundle: ...' with name

iOS:此进程已超过事件进程断言的最大允许数量

objective-c - 比较在不使用 rawValue 的情况下在 Swift 中包装 NS_ENUM 的 NSNumber 属性