NSURLConnection 在另一个线程中启动。未调用委托方法
NSURLConnection started in another thread. Delegate methods not called
我在另一个线程中启动了一个 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;
在主线程上 运行 时一切正常。我怎样才能 运行 在另一个线程上连接并在同一线程上调用委托方法?
是的,这是 NSURLConnection
的众所周知的行为,因为它需要一个 运行 循环来处理委托事件。最常见的解决方案是 (a) 用 initWithRequest:delegate:startImmediately:
实例化它,其中 startImmediately
是 FALSE
; (b) 手动 scheduleInRunLoop:forMode:
将其安排在主 运行 循环中;然后 (c) start
连接。
但是,如您所见,将它分派到后台队列没有意义,因为它已经是异步的,因此您应该从主队列启动它,并且上面的 none 是必要的。您在特殊情况下使用上述模式(例如,您使用 NSOperation
子类来管理您的请求),但通常不需要。
此外,仅供参考,有效的 iOS9、NSURLConnection
已弃用,因此无论如何您应该使用 NSURLSession
。而 NSURLSession
不受此限制。
我遇到了类似的问题。我现在正在做的是在主线程中 运行ning NSURLConnection 请求 - 它是 运行ning 异步的,因此它不会减慢您的应用程序。在 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];
}
}
GCD 隐式地创建、销毁、重用线程,您调用 start 的线程有可能会在之后立即停止存在。这可能会导致代理收不到任何回调。
如果您想在后台线程中接收回调,可以使用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);
});
我在另一个线程中启动了一个 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;
在主线程上 运行 时一切正常。我怎样才能 运行 在另一个线程上连接并在同一线程上调用委托方法?
是的,这是 NSURLConnection
的众所周知的行为,因为它需要一个 运行 循环来处理委托事件。最常见的解决方案是 (a) 用 initWithRequest:delegate:startImmediately:
实例化它,其中 startImmediately
是 FALSE
; (b) 手动 scheduleInRunLoop:forMode:
将其安排在主 运行 循环中;然后 (c) start
连接。
但是,如您所见,将它分派到后台队列没有意义,因为它已经是异步的,因此您应该从主队列启动它,并且上面的 none 是必要的。您在特殊情况下使用上述模式(例如,您使用 NSOperation
子类来管理您的请求),但通常不需要。
此外,仅供参考,有效的 iOS9、NSURLConnection
已弃用,因此无论如何您应该使用 NSURLSession
。而 NSURLSession
不受此限制。
我遇到了类似的问题。我现在正在做的是在主线程中 运行ning NSURLConnection 请求 - 它是 运行ning 异步的,因此它不会减慢您的应用程序。在 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];
}
}
GCD 隐式地创建、销毁、重用线程,您调用 start 的线程有可能会在之后立即停止存在。这可能会导致代理收不到任何回调。
如果您想在后台线程中接收回调,可以使用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);
});