NSXMLParser initWithContentsOfURL timeout - PullRequest
       12

NSXMLParser initWithContentsOfURL timeout

2 голосов
/ 04 декабря 2009

Как установить тайм-аут при разборе канала с помощью 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];

Ответы [ 3 ]

3 голосов
/ 04 декабря 2009

Первый подход: с использованием селектора с задержкой

Вероятно, самый простой способ сделать это - использовать метод 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 и установлено в YES в методе parserDidEndDocument: делегата). Это сделано для того, чтобы избежать прерывания успешного разбора. После того, как это сделано, все, что нужно, это простой

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

и через тридцать секунд будет вызван ваш код прерывания синтаксического анализа, и вы сможете делать все, что вам нужно.

Второй подход: с использованием таймера

Вы могли бы упростить весь этот подход (возможно) в методе тайм-аута, используя NSTimer вместо вызова метода NSObject. Таким образом, если анализатор успешно завершает работу, вы можете просто аннулировать таймер, что позволит вам исключить предложение if в методе parsingDidTimeout (и, как следствие, также избавиться от BOOL ivar). Инициализация таймера будет выглядеть так:

NSTimer *timer = [NSTimer timerWithTimeInterval:30.0
                                         target:self
                                       selector:@selector(parsingDidTimeout)
                                       userInfo:nil
                                        repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
1 голос
/ 04 декабря 2009

Не отвечает на ваш вопрос, но у вас будет полный контроль над циклом запросов и ответов (а также асинхронность без дополнительных потоков), если вы используете NSURLConnection для загрузки данных. Вот что делает initWithContentsOfURL: под одеялом.

0 голосов
/ 20 марта 2017

Пример 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)")
        }
    }

}
...