2

私は次のようにKey-Value検証を実装しています:

- (BOOL)validateValue:(__autoreleasing id *)value forKey:(NSString *)key error:(NSError *__autoreleasing *)error
{
    NSAttributeDescription *attribute = [[self.entity attributesByName] objectForKey:key];
    if (attribute && attribute.attributeType == NSStringAttributeType) {
        *value = [NSString stringWithFormat:@"%@ modified", *value];
        return YES;
    }
    return [super validateValue:value forKey:key error:error];
}

これが実行されると、アプリがメモリ警告を受け取り、250 MBマークでクラッシュするまで、メモリは継続的に増加します。

興味深いことに、次のバリエーションでは、合計メモリフットプリントは約5MBで安定しています。

*value = [NSString stringWithFormat:@"%@", *value];
*value = [NSString stringWithFormat:@"%@ modified", NSStringFromClass([self class])];

最初のバリエーションでは、+stringWithFormatが*valueを変更せずに返すように最適化されていると思います。

2番目のバリエーションは、コンパイラーまたはObjective Cランタイムが、新しいものを割り当てずに既存のオブジェクトを返さないようにすることです。

渡された値を組み込んだ新しい文字列オブジェクトを作成したときにのみ、メモリが増加します。

やってみた

NSString * __unsafe_unretained tmp = *value;
*value = [NSString stringWithFormat:@"%@ modified", tmp];

CFStringRef tmp = (__bridge_retained CFStringRef)*value;
*value = [NSString stringWithFormat:@"%@ modified", tmp];
CFRelease(tmp);

無駄に。

私は何が間違っているのですか?

4

1 に答える 1