Использование NSScanner для разбора строки

У меня есть строка с тегами форматирования, такие как There are {adults} adults, and {children} children, У меня есть словарь, в котором ключами являются "взрослые" и "дети", и мне нужно найти значение и заменить макросы на это значение. Это полностью динамично; ключи могут быть любыми (поэтому я не могу жестко stringByReplacingString).

В прошлом я делал подобные вещи раньше, просто просматривая изменчивую строку и ища символы; удаляя то, что я уже искал из исходной строки, как я иду. Кажется, что это именно то, для чего предназначен NSScanner, поэтому я попробовал это:

NSScanner *scanner = [NSScanner scannerWithString:format];
NSString *foundString;
scanner.charactersToBeSkipped = nil;

NSMutableString *formatedResponse = [NSMutableString string];

while ([scanner scanUpToString:@"{" intoString:&foundString]) {
    [formatedResponse appendString:[foundString stringByReplacingOccurrencesOfString:@"{" withString:@""]]; //Formatted string contains everything up to the {

    [scanner scanUpToString:@"}" intoString:&foundString];

    NSString *key = [foundString stringByReplacingOccurrencesOfString:@"}" withString:@""];

    [formatedResponse appendString:[data objectForKey:key]];

}

NSRange range = [format rangeOfString:@"}" options:NSBackwardsSearch];

if (range.location != NSNotFound) {
    [formatedResponse appendString:[format substringFromIndex:range.location + 1]];
}

Проблема в том, что когда моя строка начинается с "{", сканер возвращает НЕТ, а не ДА. (Что и должно быть в документации) Так я неправильно использую NSScanner? Дело в том, что scanUpToString не включает строку, которую искали как часть ее вывода, кажется, делает ее почти бесполезной...

Может ли это быть легко изменено, чтобы делать то, что я хочу, или мне нужно переписать, используя изменяемую строку и поиск символов вручную?

1 ответ

Решение

Использование isAtEnd определить, когда остановиться. Так же { а также } не включены в результат scanUpToString:, поэтому они будут в начале следующей строки, но добавление после цикла не требуется, поскольку сканер будет возвращать отсканированное содержимое, даже если строка поиска не найдена.

// Prevent scanner from ignoring whitespace between formats. For example, without this, "{a} {b}" and "{a}{b}" and "{a}     
//{b}" are all equivalent
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@""]];
while(![scanner isAtEnd]) {
    if([scanner scanUpToString:@"{" intoString:&foundString]) {
        [formattedResponse appendString:foundString];
    }
    if(![scanner isAtEnd]) {
        [scanner scanString:@"{" intoString:nil];
        foundString = @""; // scanUpToString doesn't modify foundString if no characters are scanned
        [scanner scanUpToString:@"}" intoString:&foundString];
        [formattedResponse appendString:[data objectForKey:foundString];
        [scanner scanString:@"}"];
    }
}
Другие вопросы по тегам