#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];
}