iOS,NSURLConnection:委托不同的线程callback?

我怎样才能让NSURLConnection调用它的委托方法从一个不同的线程,而不是主线程。 我试图搞乱scheduleInRunLoop:forMode:但似乎并没有做我想要的。

我必须下载一个大文件,并频繁地中断主线程,以至于一些正在发生的渲染开始变得波涛汹涌。

NSURLRequest * request = [NSURLRequest requestWithURL:url]; NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; NSRunLoop * loop = [NSRunLoop currentRunLoop]; NSLog(@"loop mode: %@",[loop currentMode]); [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [connection start]; 

另外一件我没有看到的东西是“模式”只有两种模式被logging下来,所以没有太多真正的testing。

有任何想法吗?

谢谢

有几个选项:

  1. 在实现委托方法时,请使用dispatch_async
  2. 在后台线程上启动连接计划。

你可以这样做后者:

 // all the setup comes here dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSRunLoop *loop = [NSRunLoop currentRunLoop]; [connection scheduleInRunLoop:loop forMode:NSRunLoopCommonModes]; [loop run]; // make sure that you have a running run-loop. }); 

如果要保证正在运行哪个线程,请将调用适当地replace为dispatch_get_global_queue()

如果你想在一个单独的线程执行下载,我敢肯定这些是你正在寻找的机器人…

 - (void) dispatchRequest{ self->finished = NO; NSMutableURLRequest* request = //Formulate your request NSThread* download_thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadThreadLoop:) object:request]; [download_thread start]; } - (void) downloadThreadLoop:(NSMutableURLRequest*) request{ NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; while(!self->finished]){ //This line below is the magic! [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ //... } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ //... } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ //... } - (void)connectionDidFinishLoading:(NSURLConnection *)connection{ //... self->finished = YES; } 

如果你确实需要在一个新的线程中下载,可能会更容易detachNewThreadSelector:toTarget:withObject: ,setup(and destroy)一个NSAutoreleasePool ,然后使用NSDatadataWithContentsOfURL:之一的同步select器。 这将不会使用asynchronousNSURLConnectionDelegate

因为这个调用是同步的,直到文件下载完成才会返回,这会阻塞主线程,但是因为你在新线程中,所以不会。 请注意,这通常是令人沮丧的行为。 主线程中是否有其他代码可以优化?

NSURLConnection已经在asynchronous执行主线程的下载。 如果我理解你的问题,你想委托消息被发送到主线程以外的线程? 你不能这样做,因为你不能修改NSURLConnection的内部实现。 我可以想到两种方法来模拟这个。

  1. 创build一个NSURLConnection的sublcass(例如MyURLConnection ),它将自己指定为自己的委托。 请注意,这会产生一个有意的保留周期,所以要小心。 MyURLConnection应该定义一个支持NSURLConnectionDelegate的新delegate 。 我们称之为finalDelegate 。 当MyURLConnection处理它自己的委托消息时,将它们转发或分配给任何你喜欢的线程的finalDelegate

  2. 类似于选项#1,但没有子类。 在主线程上处理NSURLConnection委托方法,并将它们转发/分派给你喜欢的任何线程。

主要的区别是,如果你想要一个可重复使用的子类,或者这是一个一次性的实现。

编辑:添加了如何在后台运行代码的build议

如果你要在后台处理响应,我将使用操作或大中央调度。 不需要搞乱运行循环和创build线程。 查看Apple的“ 并发编程指南” 。