我启动网络请求,假设不需要登录凭据来与目标服务器通信。如果需要它们,那么我会收到身份验证质询,此时我会显示一个请求来自用户的凭据的视图。提供它们后,我使用这些凭据重新启动网络请求。
只要我一次只做一个请求,这一切都很好,很花哨。但我不是,通常。
当两个请求都被启动时,我得到第一个挑战,并提示提示(使用-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对象。如果需要访问当前线程的运行循环,可以使用类方法currentRunLoop“。我假设这适用于调用-performSelectorInBackground创建的后台线程...(当我在-startConnection:方法中执行'po [NSClassFromString(@“NSRunLoop”)currentRunLoop]时,似乎就是这种情况) )。
确实正在调用-startConnection:方法。但是在开始连接之后,我现在永远不会在其上获得任何回调。没有-connectionDid ...委托方法。 (我甚至尝试显式启动线程的运行循环,但这没有任何区别;我之前使用过这样的线程,而且我从来没有必须手动启动运行循环 - 但我现在正在抓住吸管。 ..)
我想我已经想出了一个解决方法,这样我一次只能处理一个请求,但它很笨拙,而且我想以正确的方式做到这一点。但是,我在这里错过了什么?
谢谢! 好色
答案 0 :(得分:0)
是否达到了[pool drain];
行?我猜它是。在此之后,-startConnection方法退出,此时后台线程完成并销毁。这可能不是你想要的......
你必须运行runloop。你说你这样做了,没有任何区别。这意味着你做错了。阅读Runloop section in the Threaded Programming Guide(最好转到正确的文档,而不是听取我的意见)。请注意,像-performSelectorInBackground这样有用的方法可能会使多线程看起来很吸引人,但很难。
另外,你是什么意思
'包装在@synchronized()块中, 但这没有效果,因为这些 委托方法都被调用 在同一(主要)线程'
?
@synchronized()将在主线程上执行与在后台线程上相同的操作..您认为它有什么作用?