【发布时间】:2010-06-05 16:59:31
【问题描述】:
我启动了一个网络请求,假设与目标服务器通信不需要登录凭据。如果需要它们,那么我会收到一个身份验证质询,此时我会显示一个视图,请求用户提供所述凭据。提供它们后,我使用这些凭据重新启动网络请求。
只要我一次只做一个请求,这一切都很好。但我不是,通常情况下。
当两个请求都启动时,我得到第一个挑战,并呈现提示(使用 -presentModalViewController:)。然后是第二个挑战。当它尝试显示第二个提示时我崩溃了。
我将大部分内容封装在 @synchronized() 块中,但这没有任何效果,因为这些委托方法都在同一个(主)线程上调用。文档说委托方法是在启动连接的同一线程上调用的。好的,没问题;我将使用 -performSelectorInBackground 编写一个在后台线程上运行的方法:
NSURLConnection *connection = [[NSURLConnection alloc]
initWithRequest:request
delegate:self
startImmediately:NO];
[connections addObject:connection];
[self performSelectorInBackground:@selector(startConnection:)
withObject:connection];
[connection release];
- (void)startConnection:(NSURLConnection *)connection {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[connection start];
[pool drain];
}
它应该将每个网络请求及其回调放在自己的线程上,然后我的 @synchronized() 块将生效。
-initWithRequest 的文档:... state "发送给委托的消息将在调用此方法的线程上发送。默认情况下,要使连接正常工作,调用线程的运行循环必须在默认运行中运行循环模式。”好的,我正在这样做。
他们还声明“如果您通过 NO [for startImmediately],则必须在启动之前将连接安排在运行循环中。”好的,我也在做。
此外,NSRunLoop 的文档状态“每个 NSThread 对象,包括应用程序的主线程,都有一个根据需要自动为其创建的 NSRunLoop 对象。如果您需要访问当前线程的运行循环,您可以使用类方法当前运行循环。”我假设这适用于调用 -performSelectorInBackground... 创建的后台线程...(当我在 -startConnection: 方法中执行 'po [NSClassFromString(@"NSRunLoop") currentRunLoop]' 时似乎确实如此)。
-startConnection: 方法确实被调用了。但是在启动连接后,我现在再也没有收到 any 回调了。没有 -connectionDid… 委托方法。 (我什至尝试显式地启动线程的运行循环,但这并没有什么区别;我以前使用过这样的线程,而且我以前从来没有手动启动过运行循环——但我现在抓住了稻草。 ..)
我想我想出了一种解决方法,一次只处理一个请求,但它很笨拙,我想以正确的方式做到这一点。但是,我在这里错过了什么?
谢谢! 兰迪
【问题讨论】:
标签: cocoa networking multithreading