如何在OS X控制台应用程序中使用NSURLConnection处理错误条件?

时间:2012-05-10 01:41:45

标签: objective-c macos console-application

我看到有时加载URL失败的情况,但是它非常“失败”。当主机无法访问(即VPN未连接)时,似乎+[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:]经常挂起以下回溯:

(gdb) bt
#0  in mach_msg_trap ()
#1  in mach_msg ()
#2  in __CFRunLoopServiceMachPort ()
#3  in __CFRunLoopRun ()
#4  in CFRunLoopRunSpecific ()
#5  in +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] ()
#6  in -[NSThread main] ()
#7  in __NSThread__main__ ()
#8  in _pthread_start ()
#9  in thread_start ()

我已经实现了- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error,但它永远不会被调用。

我正在构建NSURLRequest,如下所示:

NSURLRequest *theRequest = 
    [NSURLRequest requestWithURL:[NSURL URLWithString:url]
                     cachePolicy:NSURLRequestReloadIgnoringCacheData
                 timeoutInterval:5.0];

所以我假设不是无限期地悬挂,请求应该在5秒后超时。这种情况没有发生。

我应该注意到,这发生在Mac OS X的控制台应用程序中(它是iOS库的测试框架)。我想知道运行循环配置是否发生了“奇怪”的事情。 (从跟踪中看,它似乎可能试图从它运行的运行循环中启动一个新的运行循环?!)

有什么想法吗?

编辑:由于这不是Cocoa应用程序,我必须手动运行run循环。这似乎可能是问题的一部分。

2 个答案:

答案 0 :(得分:1)

我同意你提供的超时时间似乎应该启动。可能存在错误。

您可以通过在尝试连接之前检查网络可访问性来稍微改善问题。请参阅SCNetworkReachability API

你也可以通过在运行循环上安装一个计时器来强加你自己的超时 - 你在你控制的线程上运行一个计时器,而不是框架在后台运行的那个 - 并在取消连接时火了。

答案 1 :(得分:0)

我解决了这个问题。出现问题是因为我没有给运行循环足够的时间。我有一些类似的代码:

[[NSRunLoop currentRunLoop] runUntilDate:
    [NSDate dateWithTimeIntervalSinceNow:5];

这只会导致运行循环运行5秒,这足够让我无法从URLConnection获得回调说它失败了。我把它改成了更像这样的东西,它起作用了:

[[NSRunLoop currentRunLoop] runUntilDate:
    [NSDate dateWithTimeIntervalSinceNow:10];

我认为在回溯中看到的这种副作用是,URLConnection对象在尝试进行回调时无法检测到运行循环已经停止,而在mach_msg_trap中它是可能等待它永远不会收到的答复。我不能完全解释这种行为,但这是一般理论。 ; - )