异步请求不进入竣工块 [英] Async request does not enter completion block

查看:139
本文介绍了异步请求不进入竣工块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下code是为了我更好地理解 [NSURLConnection的sendAsynchronousRequest:队列:completionHandler]。

的NSLog 语句中的 completionHandler 块,但是当我在运行此main.m文件在通过命令行项目X code,它永远不会进入 completionHandler 块。我已经使用了不同的队列, mainQueue currentQueue 但既不工作尝试。

我的预感是,请求完成之前队列被释放,并保留周期是参与。

 #进口<基金会/ Foundation.h>INT主(INT ARGC,为const char * argv的[]){
    @autoreleasepool {
        NSCache * myCache = [[NSCache的alloc]初始化];        NSArray的*图像= @
         @http://i.stack.imgur.com/E66qr.png
         @http://www.tiempoyquimera.com/wp-content/uploads/2010/01/Euro-Trash-Girl-2010.jpg
         @\"http://1.bp.blogspot.com/-Mxd8AB2nbQY/UYCISJiQz3I/AAAAAAAAAH8/Tc43U8aa9dM/s1600/Tarantino10colhans_1460858i.jpg\",
         @的https://awestruckwanderer.files.word$p$pss.com/2014/02/alan-watts.png
         @http://www.esalen.org/sites/default/files/photo_images/20120201_DELLIS__MG_9612_711.jpg];        对于(图像中的NSString *图片){
            NSURL * myURL = [NSURL URLWithString:图片];
            *的NSURLRequest请求= [[的NSURLRequest页头] initWithURL:myURL];            的NSLog(@能处理的请求%@,@([NSURLConnection的canHandleRequest:请求]));
            NSOperationQueue *队列= [[NSOperationQueue的alloc]初始化];            [NSURLConnection的sendAsynchronousRequest:要求
                                               队列:[NSOperationQueue mainQueue]
                                   completionHandler:^(NSURLResponse *响应,NSData的*数据,NSError *错误){
                                       的NSLog(@在完成处理程序);
                                       如果(!错误)
                                       {
                                           //保存数据和URL作为关键缓存
                                           的NSLog(@图片添加到高速缓存);
                                           [myCache的setObject:数据
                                                       forKey:myURL];
                                       }其他
                                       {
                                           的NSLog(@图像不添加到缓存);
                                       }
                                   }];
        }
    }
    返回0;
}


解决方案

  

我的预感是,请求完成之前队列被释放,并保留周期涉及


不太。保留周期没有涉及。坚持是参与。您在函数这样做。它退出的立即的 - 异步的东西(网络和随后的回调)是异步的,所以它会晚一点,的如果的,我们有过任何持久性。但是,我们不知道。 退出,这意味着的整个该死的节目的被拆除, KABOOM 之前,有任何机会做任何网络,更不用说回调到网络后完成处理。

现在的东西在现实生活中如何发生这种对比。在实际的iOS应用,做的的退出,因为它会调用 UIApplicationMain ,其中循环,直到该应用程序将被终止。

  INT主(INT ARGC,CHAR *的argv [])
{
    @autoreleasepool {
        返回UIApplicationMain(ARGC,ARGV,零,
            NSStringFromClass([AppDelegate类]));
    }
}

在这code, UIApplicationMain 只是继续工作,直到它被中止或终止。同时,类和实例如雨后春笋般的生活,他们坚持,因为 UIApplicationMain 不会停止。例如:

  @implementation MyViewController
- (无效){的someMethod
    // ...
    [NSURLConnection的sendAsynchronousRequest:要求
         队列:[NSOperationQueue mainQueue]
         completionHandler:^(NSURLResponse *响应,NSData的*数据,NSError *错误){
             // ...
    }
}
@结束

现在,从某种意义上说,同样的事情发生了:的someMethod 立即退出。但是,我们的节目总体仍在运行! UIApplicationMain 有一个运行循环和运行的循环仍在循环。因此,事情生活,所以现在异步材料可能发生 - 我们可以通过网络,然后调用回调

The following code is an attempt to me better understand [NSURLConnection sendAsynchronousRequest:queue:completionHandler].

There are NSLog statements in the completionHandler block, but when I run this in main.m in XCode from a command line project, it never enters the completionHandler blocks. I've tried using the different queues, mainQueue and currentQueue but neither work.

My hunch is that the queue is being deallocated before the request is completed and that retain cycles are involved.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSCache *myCache = [[NSCache alloc] init];

        NSArray *images = @[
         @"http://i.stack.imgur.com/E66qr.png",
         @"http://www.tiempoyquimera.com/wp-content/uploads/2010/01/Euro-Trash-Girl-2010.jpg",
         @"http://1.bp.blogspot.com/-Mxd8AB2nbQY/UYCISJiQz3I/AAAAAAAAAH8/Tc43U8aa9dM/s1600/Tarantino10colhans_1460858i.jpg",
         @"https://awestruckwanderer.files.wordpress.com/2014/02/alan-watts.png",
         @"http://www.esalen.org/sites/default/files/photo_images/20120201_DELLIS__MG_9612_711.jpg"];

        for (NSString *image in images){
            NSURL *myURL = [NSURL URLWithString:image];
            NSURLRequest *request = [[NSURLRequest alloc] initWithURL:myURL];

            NSLog(@"Can handle request %@", @([NSURLConnection canHandleRequest:request]));
            NSOperationQueue *queue = [[NSOperationQueue alloc]init];

            [NSURLConnection sendAsynchronousRequest:request
                                               queue:[NSOperationQueue mainQueue]
                                   completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                                       NSLog(@"In the completion handler");
                                       if (!error)
                                       {
                                           // save data to cache with url as key
                                           NSLog(@"Image Added to Cache");
                                           [myCache setObject:data
                                                       forKey:myURL];
                                       } else
                                       {
                                           NSLog(@"Image Not Added to Cache");
                                       }
                                   }];
        }
    }
    return 0;
}

解决方案

My hunch is that the queue is being deallocated before the request is completed and that retain cycles are involved

Not quite. Retain cycles are not involved. Persistence is involved. You are doing this in a main function. It exits immediately - the asynchronous stuff (the networking and the subsequent callback) is asynchronous, so it would come later, if we had any persistence. But we don't. main exits, and that means that the whole darned program is torn down, kaboom, before there is any opportunity to do any networking, let alone call back into the completion handler after the networking.

Now contrast this with how things happen in real life. In a real iOS app, main does not exit, because it calls UIApplicationMain, which loops until the app is terminated.

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil,
            NSStringFromClass([AppDelegate class]));
    }
}

In that code, UIApplicationMain just keeps running until it is aborted or otherwise terminated. Meanwhile, classes and instance have sprung to life, and they persist, because UIApplicationMain does not stop. For example:

@implementation MyViewController
- (void) someMethod {
    // ...
    [NSURLConnection sendAsynchronousRequest:request
         queue:[NSOperationQueue mainQueue]
         completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
             // ...
    }
}
@end

Now, in one sense, exactly the same thing happens: someMethod exits immediately. But our program overall is still running! UIApplicationMain has a run loop and that run loop is still cycling. Thus, things live on, and so now the asynchronous material can happen - we can network and then call the callback.

这篇关于异步请求不进入竣工块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆