0

私は、さまざまな CF オブジェクト タイプを含むことができ、呼び出し元が CFRelease に必要とする CFDictionaryRef を返すベンダー API を使用しています。より簡単に操作できるように NSDictionary にキャストし、キャストに関して要素を正しく処理していることを確認したいと思います。

フリーダイヤルのブリッジされた型 (CFString、CFNumber など) は NSDictionary によって処理されるように見え、NS 型を取得することができます。カバーの下でブリッジキャストが行われます)。

非フリー ブリッジ型 (CFHost など) の場合、 -valueForKey: からの結果を CF 型にブリッジ キャストしてそこから移動できるように見えますが、その値を解放する必要があるかどうかについては確信が持てません。 .

この問題を示すサンプル コードを次に示します。これは物事を処理する正しい方法ですか?

// Caller is responsible for releasing returned value
//
+ (CFDictionaryRef)someCFCreateFunctionFromVendor
{
    CFMutableDictionaryRef cfdict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(cfdict, CFSTR("string1"), CFSTR("value"));
    int i = 42;
    CFDictionarySetValue(cfdict, CFSTR("int1"), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i));

    CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, CFSTR("myhost"));
    CFDictionarySetValue(cfdict, CFSTR("host1"), host);
    return cfdict;
}

+ (void)myMethod
{
    NSDictionary *dict = CFBridgingRelease([self someCFCreateFunctionFromVendor]);
    for (NSString *key in [dict allKeys]) {
        id value = [dict valueForKey:key];
        NSLog(@"%@ class: %@", key, [value class]);

        if ([value isKindOfClass:[NSString class]]) {
            NSString *str = (NSString *)value;
            NSLog(@"%@ is an NSString with value %@", key, str);
        } else if ([value isKindOfClass:[NSNumber class]]) {
            NSNumber *num = (NSNumber *)value;
            NSLog(@"%@ is an NSNumber with value %@", key, num);
        } else if ([value isKindOfClass:[NSHost class]]) {
            NSLog(@"%@ is an NSHost", key); // never hit because no toll-free bridge to NSHost
        } else {
            NSLog(@"%@ is an unexpected class", key);
        }

        // Sample handling of non-toll-free bridged type
        if ([key isEqualToString:@"host1"]) {
            CFHostRef host = (__bridge CFHostRef)value;
            NSArray *names = (__bridge NSArray *)(CFHostGetNames(host, false));
            NSLog(@"host1 names: %@", names);
            // I don't think I need to CFRelease(host) because ARC is still handling value
        }
    }
}

出力...

string1 class: __NSCFConstantString
string1 is an NSString with value strvalue 
int1 class: __NSCFNumber
int1 is an NSNumber with value 42
host1 class: __NSCFType
host1 is an unexpected class
host1 names: ( myhost )
4

1 に答える 1

0

皮肉なことに、コードの唯一のエラーは Core Foundation の非 ARC のものです。あなたの+someCFCreateFunctionFromVendorメソッドはCFNumberCreate()CFHostCreateWithName()を呼び出します。どちらも Create 関数ですがCFRelease()、オブジェクトを辞書に追加した後はオブジェクトを呼び出しません。そうすべき。そうでなければ、それは漏れです。ちなみに、静的アナライザーはそれをキャッチします。( の場合はCFNumber、作成を別の行に分割して、オブジェクトを辞書に追加した後に参照できるようにする必要があることを意味します。)

+myMethodそのコードはホスト オブジェクトの所有権を取得しないため、ホスト オブジェクトを解放しないでください。ARCとは関係ありません。MRR (手動保持/解放) コードでも解放しません。

于 2013-06-05T21:12:32.787 に答える