Iphone NSXMLParser initWithContentsOfURL超时

Iphone NSXMLParser initWithContentsOfURL超时,iphone,nsxmlparser,Iphone,Nsxmlparser,当我使用initWithContentsOfURL解析提要时,如何设置超时。有时,我们的提要返回一个空白响应,然后它将永远尝试解析提要。我想设置30秒左右的超时时间,这样会弹出UIAlertView,然后尝试重新分析提要 NSURL *feedURL = [[NSURL alloc] initWithString:URL]; NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:feedURL];

当我使用initWithContentsOfURL解析提要时,如何设置超时。有时,我们的提要返回一个空白响应,然后它将永远尝试解析提要。我想设置30秒左右的超时时间,这样会弹出UIAlertView,然后尝试重新分析提要

    NSURL *feedURL = [[NSURL alloc] initWithString:URL];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:feedURL];
    [parser setDelegate:self];
    [parser setShouldProcessNamespaces:NO];
    [parser setShouldReportNamespacePrefixes:NO];
    [parser setShouldResolveExternalEntities:NO];

    [parser parse];

第一种方法:使用延迟选择器

可能最简单的方法是使用NSObject的方法。您可以将某些方法
parsingDidTimeout
定义为:

- (void)parsingDidTimeout {
    if(self.parsingDidComplete == NO) {
        [self.parser abortParsing];
        // Create your error and display it here

        // Try the fetch and parse again...
    }
}
这要求您将解析器作为实例变量(
self.parser
)挂起,以便从定义的方法中取消它。它还要求您的解析器委托人跟踪解析器是否已完成(
self.parsingDidComplete
,可以在委托人的
parserdinddocument:
方法中默认为
NO
,并设置为
YES
)。这是为了避免中止成功的分析。完成后,只需简单的

[self performSelector:@selector(parsingDidTimeout) withObject:nil afterDelay:30];
30秒后,你的解析中止代码将被调用,你可以做任何你需要做的事情

第二种方法:使用计时器

通过使用一个而不是NSObject方法调用,可以在timeout方法中简化整个方法(可以说)。这样,如果解析器成功完成,您可以简单地使计时器无效,从而消除
parsingDidTimeout
方法中的
if
子句(因此,还可以去掉
BOOL
ivar)。计时器初始化如下所示:

NSTimer *timer = [NSTimer timerWithTimeInterval:30.0
                                         target:self
                                       selector:@selector(parsingDidTimeout)
                                       userInfo:nil
                                        repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

不会回答您的问题方向,但如果您用于下载数据,则您可以完全控制请求和响应周期(以及无附加线程的异步性)。这就是
initWithContentsOfURL:
在封面下所做的。

Swift 3使用
NSTimer
aka
Timer的示例

func startParseTimeoutTimer() {
    Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (_) in
        if (self.busy) {
            self.parser?.abortParsing()
            self.parser = nil
            print("Show UI as NOT busy; we aborted for timeout \(Thread.current.isMainThread)")
        }
    }

}

第二种方法的问题是计时器被添加到当前运行循环中。配对过程是同步的,而不是异步的。如果读取暂停且超时失败,则线程已被占用,因此将无法执行超时。尽管如此,我还是喜欢第二种解决方案,因为如果读取成功,计时器可以取消。