Я называю свой служебный метод так:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"dd.MM.yy HH:mm"];
NSString *dateString = [dateFormat stringFromDate:[NSDate date]];
return [[Environment sharedInstance].versionLabelFormat replaceTokensWithStrings:
@"VERSION", APP_VERSION,
@"BUILD", APP_BULD_NUMBER,
@"DATETIME", dateString,
nil ];
Это метод категорий NSString
-(NSString *)replaceTokensWithStrings:(NSString *)firstKey,... NS_REQUIRES_NIL_TERMINATION{
NSString *result = self;
va_list _arguments;
va_start(_arguments, firstKey);
for (NSString *key = firstKey; key != nil; key = va_arg(_arguments, NSString*)) {
// The value has to be copied to prevent crashes
NSString *value = [(NSString *)(va_arg(_arguments, NSString*))copy];
if(!value){
// Every key has to have a value pair otherwise the replacement is invalid and nil is returned
NSLog(@"Premature occurence of nil. Each token must be accompanied by a value: %@", result);
return nil;
}
result = [result replaceToken:key withString:value];
}
va_end(_arguments);
// Check if there are any tokens which were not yet replaced (for example if one value was nil)
if([result rangeOfString:@"{"].location == NSNotFound){
return result;
} else {
NSLog(@"Failed to replace tokens failed string still contains tokens: %@", result);
return nil;
}
}
. Нет, в следующей строке мне пришлось добавить оператор copy
, иначе был бы Зомби сdateString
:
NSString *value = [(NSString *)(va_arg(_arguments, NSString*))copy];
Чтобы быть более точным, Отчет о Зомби сказал мне следующее:
1 Malloc NSDateFormatter stringForObjectValue:
Autorelease NSDateFormatter stringForObjectValue:
2 CFRetain MyClass versionString:
3 CFRetain replaceToken:withString:
2 CFRelease replaceToken:withString:
1 CFRelease replaceTokensWithStrings: ( One release too much!)
0 CFRelease MyClass versionString:
-1 Zombie GSEventRunModal
Хотя оператор copy
, кажется, решает проблему, я хотел бы понять, что не соответствует ARC -коду, чтобы BAD_ACCESS
возникало без copy
для строки значения.