私は書式文字列を使ってURLのパス部分を簡単に設定できる方法を書いています。もともと、私はちょうどinitWithFormat:
にフォーマット文字列とargsを渡しましたが、誰かが私の中を通るようになっています。 initWithFormat:
に行く前に、メソッドを%でエンコードしてメソッドを変更しました。このvarargs関数を安全に処理する方法はありますか?
[request setUrlWithFormat:@"users/%@/timesheets", username]
のように、username
はbmauter
またはb mauter
となります。
- (void) setUrlWithFormat:(NSString *)format, ... {
// loop through varargs and cleanse them for the URL path
va_list args;
va_start(args, format);
NSMutableArray *cleaned = [[NSMutableArray alloc] init];
for(NSString *s = format; s != nil; s = va_arg(args, NSString *)) {
if (s == format) continue;
[cleaned addObject:[s stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]];
}
va_end(args);
// put the cleansed values back into a varargs list
__unsafe_unretained id *argList = (__unsafe_unretained id *) calloc(1UL, sizeof(id) * cleaned.count);
for (NSInteger i = 0; i < cleaned.count; i++) argList[i] = cleaned[i];
NSString* result = [[NSString alloc] initWithFormat:format, *argList];
free(argList);
[self setUrl:result];
}
時々私は最初for
ループライン上のEXC_BAD_ACCESSでクラッシュ。時々、私はinitWithString:
行でクラッシュします。ほとんどの場合、それは完璧に動作します。
更新:もう一度@uliwitnessに感謝します。他の誰かが私が結んだことを見たい場合は、ここに行きます:
- (void) setUrlWithFormat:(NSString *)format, ... {
DLog(@"format=%@", format);
va_list args;
va_start(args, format);
NSMutableString *result = [format mutableCopy];
NSRange range = [result rangeOfString:@"%@"];
while(range.location != NSNotFound) {
NSObject *obj = va_arg(args, NSObject *);
NSString *dirty = nil;
if ([obj isKindOfClass:[NSString class]]) dirty = (NSString *)obj;
else dirty = [NSString stringWithFormat:@"%@", obj];
NSString *clean = [dirty stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];
DLog(@"dirty=%@, clean=%@", dirty, clean);
[result replaceCharactersInRange:range withString:clean];
range = [result rangeOfString:@"%@"];
}
va_end(args);
DLog(@"result=%@", result);
[self setUrl:result];
}
ありがとうございます。私が投稿した直後に、フォーマット指定子の数を数えなければならないと分かりました。それを知ることは、これまでに見つかったすべてのクラッシュを最初の 'for'ループで解決します。私はまだ2回目の 'for'ループクラッシュに悩まされています。そのコードは 'NSArray'をvarargsリストにパッケージ化しようとしています。私はそのコードをここに見つけ、私の目的のためにそれを微調整しました。理想的には 'NSString'は' initWithFormat:argsInArray':メソッドの型を持ちます。それが起こるまでは、フォーマット指定子を自分で置き換えなければならないことは間違いありません。 – bmauter