Исходя из этого ТАКОГО вопроса, заданного несколько часов назад, я решил реализовать метод swizzled, который позволит мне принять форматированный NSString
в качестве аргумента формата в stringWithFormat
не пропускается при пропуске одной из пронумерованных ссылок arg (%1$@, %2$@
)
У меня это работает, но это первая копия, и, учитывая, что этот метод потенциально может вызываться сотни тысяч раз за запуск приложения, мне нужно отослать это от некоторых экспертов, чтобы увидеть, имеет ли этот метод любые красные флаги, значительные потери производительности или оптимизации
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
@implementation NSString (UAFormatOmissions)
+ (id)uaStringWithFormat:(NSString *)format, ... {
if (format != nil) {
va_list args;
va_start(args, format);
// $@ is an ordered variable (%1$@, %2$@...)
if ([format rangeOfString:@"$@"].location == NSNotFound) {
//call apples method
NSString *s = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
va_end(args);
return s;
}
NSMutableArray *newArgs = [NSMutableArray arrayWithCapacity:NUMARGS(args)];
id arg = nil;
int i = 1;
while (arg = va_arg(args, id)) {
NSString *f = [NSString stringWithFormat:@"%%%d\$\@", i];
i++;
if ([format rangeOfString:f].location == NSNotFound) continue;
else [newArgs addObject:arg];
}
va_end(args);
char *newArgList = (char *)malloc(sizeof(id) * [newArgs count]);
[newArgs getObjects:(id *)newArgList];
NSString* result = [[[NSString alloc] initWithFormat:format arguments:newArgList] autorelease];
free(newArgList);
return result;
}
return nil;
}
Основной алгоритм:
- поиск строки формата для переменных
%1$@
, %2$@
путем поиска %@
- если не найден, вызовите обычную строкуWithFormat и верните
- еще, перебрать арг
- если формат имеет переменную позиции (
%i$@
) для позиции i, добавьте arg в новый массив arg
- иначе, не добавляйте аргумент
- взять новый массив arg, преобразовать его обратно в
va_list
и вызвать initWithFormat:arguments:
, чтобы получить правильную строку.
Идея состоит в том, что я вместо этого выполняю все вызовы [NSString stringWithFormat:]
через этот метод.
Многим это может показаться ненужным, но нажмите на указанный вопрос SO (первая строка), чтобы увидеть примеры того, почему мне нужно это сделать.
Идеи? Мысли? Лучшие реализации? Лучшие решения?