GCD和异步NSURLConnection

ban*_*isa 24 objective-c grand-central-dispatch ios

我知道如果我创建一个NSURLConnection(标准的异步),它将在同一个线程上回调.目前这是我的主线程.(工作也很好).

但是我现在使用相同的代码来做其他事情,我需要让我的UI保持活泼......

如果我做

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    /* and inside here, at some NSURLConnection is created */


});
Run Code Online (Sandbox Code Playgroud)

..我的NSURLConnection是否可能被创建,但我的线程在url连接返回之前消失了?

我是GCD的新手.在我的url连接返回之前,如何让线程保持活动状态,或者有更好的方法可以做到这一点?

Fir*_*eer 37

所以问题实际上不是你的块运行的线程的生命周期,事实上这个特定的线程不会配置runloop并且正在运行以接收从连接返回的任何事件.

那你怎么解决这个问题呢?有不同的选择可供思考.我可以列出一些,我相信其他人会列出更多.

1 - 您可以在此处使用同步连接.一个缺点是你不会得到认证,重定向,缓存等的回调.(同步连接的所有常见缺点.)加上每个连接当然会阻塞一个线程一段时间,所以如果你正在做很多这些你可能会同时阻止一些线程,这是昂贵的.

2 - 如果你的连接很简单并且你使用的是iOS5,那么你可以使用这个方法:

+ (void)sendAsynchronousRequest:(NSURLRequest *)request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))
Run Code Online (Sandbox Code Playgroud)

这将启动异步连接,然后允许您指定完成处理程序(成功或失败) NSOperationQueue,您希望在其上安排该块.

同样,你的缺点是没有得到你可能需要的回调,你可能需要进行身份验证,缓存等等.但至少你没有线程挂在被飞行中的连接阻止.

3 - iOS5的另一个选项是为所有委托回调设置队列:

- (void)setDelegateQueue:(NSOperationQueue*) queue NS_AVAILABLE(10_7, 5_0);

如果使用它,那么所有委托方法都将在您指定的任何NSOperationQueue的上下文中执行.所以这与选项#2类似,期望您现在可以获得所有委托方法来处理身份验证,重定向等.

4 - 您可以设置自己专门用于管理这些连接的线程.在设置该线程时,您可以适当地配置runloop.这在iOS4和5中可以正常工作,显然可以为你提供你想要处理的所有委托回调

5 - 您可能会想到异步连接处理的哪些部分确实干扰了您的UI.通常,启动连接或接收委托回调并不昂贵.昂贵(或不确定)的成本通常用于处理您最后收集的数据.这里要问的问题是你真的通过在一些队列上安排一个块来节省时间,只是为了启动一个异步连接,它会立即关闭并在另一个线程上做它的事情吗?

所以你可以从主线程开始连接,并接收主线程上的所有委托回调,然后在你的那些委托方法的实现中触发你需要在其他队列或线程上做的任何昂贵的工作.

所以像这样:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {      
        // go ahead and receive this message on the main thread
        // but then turn around and fire off a block to do the real expensive work

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

         // Parse the data we've been collecting

        });

    }
Run Code Online (Sandbox Code Playgroud)

同样,这并不全面.根据您的具体需求,有很多方法可以解决这个问题.但我希望这些想法有所帮助.


Ton*_*ion 9

正如你的线程为什么消失(以及将来参考)的答案一样,NSURLConnection需要一个runloop.如果您已添加

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
Run Code Online (Sandbox Code Playgroud)

你会看到连接正常运行,线程不会消失,直到连接完成.