【问题标题】:NSXMLParser initWithContentsOfURL timeoutNSXMLParser initWithContentsOfURL 超时
【发布时间】:2010-12-23 09:35:24
【问题描述】:

在使用 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];

【问题讨论】:

    标签: iphone nsxmlparser


    【解决方案1】:

    使用 NSTimer aka Timer 的 Swift 3 示例

    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)")
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

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

      可能最简单的方法是使用 NSObject 的performSelector:withObject:afterDelay: 方法。您可以像这样定义一些方法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,可以默认为 NO 并在委托的 parserDidEndDocument: 方法中设置为 YES)。这是为了避免中止成功的解析。完成后,只需要一个简单的

      [self performSelector:@selector(parsingDidTimeout) withObject:nil afterDelay:30];

      三十秒后,您的解析中止代码将被调用,您可以做任何您需要做的事情。

      第二种方法: 使用计时器

      您可以通过使用NSTimer 而不是 NSObject 方法调用,在超时方法中使整个方法(可以说)更简单。这样,如果解析器成功完成,您可以简单地使计时器无效,从而消除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];

      【讨论】:

      • 第二种方法的问题是定时器被添加到当前运行循环中。配对过程是同步的,而不是异步的。如果读取停止并且未能超时,则线程被占用,因此将永远无法执行超时。尽管如此,我更喜欢第二种解决方案,因为如果读取成功,可以取消计时器。
      【解决方案3】:

      不回答您的问题方向,但如果您使用 NSURLConnection 下载数据,您将可以完全控制请求和响应周期(以及无需额外线程的异步性)。这就是 initWithContentsOfURL: 在幕后所做的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-07
        • 2012-08-13
        • 2013-02-21
        相关资源
        最近更新 更多