我在另一个线程中启动NSURLConnection:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^{
NSURLConnection *connection = [NSURLConnection connectionWithRequest:[request preparedURLRequest] delegate:self];
[connection start];
});
但是我的委托方法没有被调用:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data;
在主线程上运行时一切都很好。如何在另一个线程上运行连接并获取在同一线程上调用的委托方法?
答案 0 :(得分:5)
GCD隐式创建,销毁,重用线程,并且您调用的线程有可能会在之后立即停止存在。这可能导致代理没有收到任何回调。
如果您希望在后台线程中收到回调,可以使用setDelegateQueue
或sendAsynchronousRequest:queue:completionHandler:
方法:
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:NO];
[connection setDelegateQueue:[[NSOperationQueue alloc] init]];
[connection start];
通过GCD在后台线程中启动NSURLConnection的最简单方法是:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
NSURLResponse* response = nil;
NSError* error = nil;
[NSURLConnection sendSynchronousRequest:request] returningResponse:&response error:&error];
NSLog(@"%@", response);
});
答案 1 :(得分:2)
是的,这是众所周知的NSURLConnection
行为,因为它需要一个运行循环来处理委托事件。最常见的解决方案是(a)使用initWithRequest:delegate:startImmediately:
对其进行实例化,其中startImmediately
为FALSE
; (b)手动scheduleInRunLoop:forMode:
在主运行循环中安排它;然后(c)start
连接。
但是,正如你在这里所说的那样,没有必要将它分配给后台队列,因为它已经是异步的,所以你应该从主队列中启动它,而上面没有一个是必要。您在特殊情况下使用上述模式(例如,您使用NSOperation
子类来管理您的请求),但通常不需要。
另外,仅供参考,有效的iOS9,NSURLConnection
已被弃用,因此您应该使用NSURLSession
。并且NSURLSession
不受此限制。
答案 2 :(得分:1)
我有类似的问题。我现在正在做的是在主线程中运行NSURLConnection请求 - 它以异步方式运行,因此它不会减慢你的应用程序的速度。在connectionDidFinishLoading中,我运行以下代码来处理我的调用结果。我执行检查,因为我有NSURLConnection调用,可能会触发其他网络调用。由于他们已经在后台线程上运行,我不想开始新的。
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if ([NSThread isMainThread]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
[self processFinishLoading:connection];
});
}
else {
[self processFinishLoading:connection];
}
}