Простой способ отменить текущую операцию синтаксического анализа NSXMLParser?

#iphone #objective-c #ios #nsurlconnection #nsxmlparser

#iPhone #objective-c #iOS #nsurlconnection #nsxmlparser

Вопрос:

Хорошо.

Допустим, у меня есть UITextField где пользователь может ввести URL-адрес, такой как:

 http://foo.bar/foo/bar.asmx
  

Теперь, если приложению будет отправлен правильный URL, оно ответит NSData размером в байтах около 450-700 в зависимости от возвращаемых значений, значения различаются у разных пользователей. Вызов занимает около секунды или около того, и NSXMLParser также в течение секунды анализирует данные.

Но всякий раз, когда мы вводим, например:

 http://apple.com/foo/bar.asmx
  

Мы получаем сообщение NSData с размером байта около 9700. И анализатор анализирует эти данные до бесконечности. И я понятия не имею, как выдать правильное сообщение об ошибке, когда пользователь ввел неверный URL, что привело к NSXMLParser разбору на бесконечность.

Мы пытались использовать это.

в

 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
{

xmlParser = [[NSXMLParser alloc] initWithData:myData];
[xmlParser setDelegate:self];
[xmlParser shouldResolveExternalEntities:YES];
[xmlParser parse];
[self performSelector:@selector(timeOutMyParser:) withObject:nil afterdelay:15];

[xmlParser release];
[connection release];
[myData release];

}
  

Теперь, что происходит с этим кодом, так это то, что performSelector никогда не выполняется, поскольку он постоянно выполняет синтаксический анализ.

Итак, подведем итог:

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

Есть ли какой-либо ПРОСТОЙ способ отменить текущую операцию синтаксического анализа?

Комментарии:

1. Селектор никогда не запускается, поскольку анализатор выполняет синтаксический анализ в главном потоке, а основной поток блокируется синтаксическим анализом. Что я делаю, так это помещаю синтаксический анализ в NSOperation, помещаю эту NSOperation в NSOperationQueue, что сделает его потоковым приложением. Затем вы могли бы вызвать abortParsing из потока или сами методы делегирования анализатора.

2. Ммм, хорошо, у вас есть какие-либо ресурсы или примеры о том, как я мог бы остановить поток, если операция синтаксического анализа занимает слишком много времени?

Ответ №1:

На самом деле вызов [xmlParser parse] возвращает логическое значение, которое будет YES, если синтаксический анализ прошел успешно. Возвращает NO в противном случае. Итак, просто получите логическое значение.

 BOOL parserSucceeded = [xmlParser parse];
  

Во время синтаксического анализа, если вы получаете неверные данные в вашем XML или если вы хотите остановить синтаксический анализ по условию, вы можете отменить синтаксический анализ, вызвав

 [parser abortParsing];
  

И вы можете проверить статус и выполнить соответствующие действия.

 BOOL parserSucceeded = [xmlParser parse];

if (parserSucceeded) {

    // Parser Succeeded

} else {

    // Parser Failed/Aborted
}
  

Комментарии:

1. Мы не можем получить доступ к переменной parsersucceeded, поскольку инструкция [xmlparser parse] запускает анализатор и блокирует основной поток. И если URL, например: apple.com операция синтаксического анализа занимает вечность. И сбой.

2. @Da_smokes, Вы не можете определить, является ли XML допустимым или недействительным, просмотрев содержимое XML?

3. @Da_smokes, Если это так, вы можете легко прервать синтаксический анализ

4. Нет, потому что, если я введу неверный URL, я даже не получу методы делегирования анализатора, он просто застрянет на [parser parse];

5. @Da_smokes, это кажется странным. Вы распечатывали данные, используя NSLog [NSString stringWithData:data] ? Печатает ли он допустимую строку XML?

Ответ №2:

Проблема заключалась в том, что [xmlParser parse] блокировал основной поток, блокируя все.

Итак, вместо

  -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    {

    xmlParser = [[NSXMLParser alloc] initWithData:myData];
    [xmlParser setDelegate:self];
    [xmlParser shouldResolveExternalEntities:YES];
    [xmlParser parse];
    [self performSelector:@selector(timeOutMyParser:) withObject:nil afterdelay:15];

    [xmlParser release];
    [connection release];
    [myData release];

    }
  

я сделал это.

 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
{

xmlParser = [[NSXMLParser alloc]init];
[xmlParser setDelegate:self];
[xmlParser shouldResolveExternalEntities:YES];

[self performSelectorInBackground:@selector(someFunction) withObject:xmlParser];

[xmlParser release];
[connection release];
[myData release];

}
  

Где someFunction находится что-то вроде этого.

 -(void)someFunction:(NSXMLParser *)parser
{

parser = [[NSXMLParser alloc]initWithData:myData];
[parser setDelegate:self];
[parser parse];

[parser release];

}