it-swarm.com.de

NSString zu CFStringRef und CFStringRef zu NSString in ARC?

Ich versuche zu verstehen, wie ein NSString von einem CFStringRef in ARC korrekt abgerufen werden kann. Dasselbe gilt für die umgekehrte Richtung: CFStringRef bis NSString in ARC?

Was ist der richtige Weg, um dies zu tun, ohne Speicherlecks zu verursachen?

79
zumzum

Normalerweise

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

und

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

Nun, wenn Sie wissen wollen, warum das __bridge Schlüsselwort ist da, können Sie sich auf die Apple-Dokumentation . Dort finden Sie:

__bridge überträgt einen Zeiger zwischen Objective-C und Core Foundation ohne Eigentumsübertragung.

__bridge_retained oder CFBridgingRetain wandelt einen Objective-C-Zeiger in einen Core Foundation-Zeiger um und überträgt ihn ebenfalls Eigentum an Ihnen. Sie sind dafür verantwortlich, CFRelease oder eine verwandte Funktion aufzurufen, um das Eigentum an dem Objekt aufzugeben.

__bridge_transfer oder CFBridgingRelease verschiebt einen Nicht-Ziel-C-Zeiger auf Ziel-C und auch überträgt das Eigentum an ARC. ARC ist verantwortlich für die Abtretung des Eigentums an dem Objekt.

Dies bedeutet, dass Sie in den oben genannten Fällen das Objekt gießen, ohne den Eigentümer zu ändern. Dies bedeutet, dass Sie in keinem Fall für die Verwaltung des Speichers der Zeichenfolgen verantwortlich sind.

Es kann auch vorkommen, dass Sie aus irgendeinem Grund das Eigentum übertragen möchten.

Betrachten Sie zum Beispiel das folgende Snippet

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge NSString *)str;

    NSLog(@"%@", aNSString);

    CFRelease(str); //you have to release the string because you created it with a 'Create' CF function
}

in einem solchen Fall möchten Sie möglicherweise ein CFRelease speichern, indem Sie das Eigentum beim Casting übertragen.

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
    NSString * aNSString = (NSString *)CFBridgingRelease(str);

    NSLog(@"%@", aNSString);
}

Das Eigentum von str wurde übertragen, daher wird ARC jetzt aktiv und gibt den Speicher für Sie frei.

Auf der anderen Seite kannst du ein NSString * zu einem CFString mit einem __bridge_retained umgewandelt, sodass Sie das Objekt besitzen und es explizit freigeben müssen, indem Sie CFRelease verwenden.


Zum Einpacken kann man haben

NSString → CFString

// Don't transfer ownership. You won't have to call `CFRelease`
CFStringRef str = (__bridge CFStringRef)string;

// Transfer ownership (i.e. get ARC out of the way). The object is now yours and you must call `CFRelease` when you're done with it
CFStringRef str = (__bridge_retained CFStringRef)string // you will have to call `CFRelease`

CFString → NSString

// Don't transfer ownership. ARC stays out of the way, and you must call `CFRelease` on `str` if appropriate (depending on how the `CFString` was created)
NSString *string = (__bridge NSString *)str;

// Transfer ownership to ARC. ARC kicks in and it's now in charge of releasing the string object. You won't have to explicitly call `CFRelease` on `str`
NSString *string = (__bridge_transfer NSString *)str;
163