6

などの書式タグを含む文字列がありますThere are {adults} adults, and {children} children。キーとして「大人」と「子供」を持つ辞書があり、値を調べてマクロをその値に置き換える必要があります。これは完全に動的です。キーは何でもかまいません(したがって、 a をハードコードすることはできません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]];
}

これの問題は、文字列が "{" で始まる場合、スキャナーが YES ではなく NO を返すことです。(これは、ドキュメンテーションが起こるべきだと言っていることです)。NSScanner を悪用しているのでしょうか? scanUpToString出力の一部として検索されていた文字列が含まれていないという事実は、ほとんど役に立たないようです...

これは簡単に変更できますか、それとも変更可能な文字列を使用して手動で文字を検索する必要がありますか?

4

1 に答える 1

12

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:@"}"];
    }
}
于 2011-03-22T19:31:35.313 に答える