私は次のように私のユーティリティメソッドを呼び出します:
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
のforがないと発生するようにします。copy