NSRegularExpression: enumerateMatchesInString зависает при вызове более одного раза
В контексте приложения iPhone, которое я разрабатываю, я анализирую некоторый html для извлечения данных на карту, используя NSRegularExpression. Эта информация обновляется всякий раз, когда пользователь "сковывает" карту в новое место.
Это отлично работает в первый раз или два, но во второй или третий раз вызывается функция, приложение зависает. Я использовал профилировщик XCode, чтобы подтвердить, что я не утечка памяти, и не генерируется ошибка (приложение не завершается, оно просто сидит в исполнении в точке, показанной ниже).
Когда я рассматриваю обрабатываемый HTML-код, я не вижу, что он не завершен или иным образом искажен, когда приложение зависает.
Кроме того, если я заменил код регулярного выражения на коллекцию явно адресных строк, все будет работать так, как ожидалось.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// receivedData contains the returned HTML
NSString *result = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSError *error = nil;
NSString *pattern = @"description.*?h4>(.*?)<\\/h4>.*?\"address>[ \\s]*(.*?)<.*?zip>.*?(\\d{5,5}), US<";
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators
error:&error];
__block NSUInteger counter = 0;
// the application hangs on the next line after 1-2 times through
[regex enumerateMatchesInString:result options:0 range:NSMakeRange(0, [result length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
NSRange range = [match rangeAtIndex:2];
NSString *streetAddress =[result substringWithRange:range];
range = [match rangeAtIndex:3];
NSString *cityStateZip = [result substringWithRange:range];
NSString *address = [NSString stringWithFormat:@"%@ %@", streetAddress, cityStateZip];
EKItemInfo *party = [self addItem:address]; // geocode address and then map it
if (++counter > 4) *stop = true;
}];
[receivedData release];
[result release];
[connection release]; //alloc'd previously, so release here.
}
Я понимаю, что это будет трудно/невозможно дублировать, но мне было интересно, сталкивается ли кто-нибудь с аналогичной проблемой с NSRegularExpression или если здесь что-то явно не так.
Ответы
Ответ 1
Я также столкнулся с исключением регулярного выражения. В моем случае проблема была в кодировке символов. Так что я написал код, чтобы хорошо сочетаться с несколькими кодировками символов. Возможно, этот код поможет вам.
+ (NSString *)encodedStringWithContentsOfURL:(NSURL *)url
{
// Get the web page HTML
NSData *data = [NSData dataWithContentsOfURL:url];
// response
int enc_arr[] = {
NSUTF8StringEncoding, // UTF-8
NSShiftJISStringEncoding, // Shift_JIS
NSJapaneseEUCStringEncoding, // EUC-JP
NSISO2022JPStringEncoding, // JIS
NSUnicodeStringEncoding, // Unicode
NSASCIIStringEncoding // ASCII
};
NSString *data_str = nil;
int max = sizeof(enc_arr) / sizeof(enc_arr[0]);
for (int i=0; i<max; i++) {
data_str = [
[NSString alloc]
initWithData : data
encoding : enc_arr[i]
];
if (data_str!=nil) {
break;
}
}
return data_str;
}
Вы можете загрузить всю библиотеку категорий из GitHub и просто запустить ее. Я хочу, чтобы это помогло вам.
https://github.com/weed/p120801_CharacterEncodingLibrary
Ответ 2
Возможно, ответ на этот вопрос можно найти по адресу: NSRegularExpression enumerateMatchesInString: [...] usingBlock никогда не останавливается.
Я решил эту проблему, передав параметр NSMatchingReportCompletion как опцию и установив stop на YES, когда совпадение равно nil.