如何让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];
我没有看到的另一件事是“模式”只记录了两种模式,所以没有多少真正要测试。
有什么想法吗?
由于
答案 0 :(得分:6)
有几种选择:
dispatch_async
。你可以这样做:
// 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.
});
如果您想要保证正在运行的线程,请适当地将呼叫替换为dispatch_get_global_queue()
。
答案 1 :(得分:2)
如果你想在一个单独的线程上执行下载,我很确定这些是你正在寻找的机器人......
- (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;
}
答案 2 :(得分:0)
如果您真的需要在新线程中进行下载,detachNewThreadSelector:toTarget:withObject:
,设置(和销毁)NSAutoreleasePool
可能更容易,然后使用其中一个同步选择器,如{{} 1}} NSData
。这不会使用异步dataWithContentsOfURL:
。
因为这个调用是同步的,所以在下载文件之前它不会返回,这会阻塞主线程,但是因为你在一个新线程中,它不会。请注意,这通常是不鼓励的行为。主线程中是否还有其他可以优化的代码?
答案 3 :(得分:0)
NSURLConnection已经异步下载主线程。如果我理解你的问题,你希望委托消息在主线程以外的线程上发送?您不能这样做,因为您无法修改NSURLConnection的内部实现。我可以想出两种模拟方法。
创建NSURLConnection
(例如MyURLConnection
)的sublcass,将自己指定为自己的委托。请注意,这会产生有意的保留周期,因此请小心。 MyURLConnection
应定义支持delegate
的新NSURLConnectionDelegate
。我们称之为finalDelegate
。当MyURLConnection
处理它自己的委托消息时,在你想要的任何线程上将它们转发或发送到finalDelegate
。
与选项#1类似但没有子类。处理主线程上的NSURLConnection
委托方法,并将它们转发/发送到您喜欢的任何线程。
主要区别在于,如果您希望可重用的子类以这种方式运行,或者它是一次性实现。
编辑:添加了有关如何在后台运行代码的建议
如果你要在后台处理响应,我会使用操作或大中央调度。无需乱跑循环和创建线程。查看Apple的Concurrency Programming Guide。