CFStringRef'e NSString ve ARC'de NSString'e CFStringRef?


89

ARC'de a'dan NSStringbir almanın doğru yolunu anlamaya çalışıyorum CFStringRef? Ters yöne giden için aynı CFStringRefetmek NSStringARC içinde?

Bellek sızıntıları oluşturmadan bunu yapmanın doğru yolu nedir?


4
CFStringRef foo (__bridge CFStringRef)theNSString;veNSString *bar = (__bridge NSString *)theCFString;

Bu iki seçenek kullanıldığında gerçekte neler olduğunu ayrıntılı olarak açıklayabilir misiniz?
zumzum

Tam olarak değil. ARC kullanmıyorum, bu yüzden tek bildiğim bunu yapmanız gerektiğidir, ama nedenini

1
@GabrielePetronella ARC'nin kodlamayı kolaylaştırması, kodlamayı kısaltması ve daha okunaklı hale getirmesi ve insan hatası olasılığını azaltması gerekiyordu. Yani, şimdi yerine göre referans sayıları özen zorunda retaining ve releasenesneleri -ing, şimdiki gibi "güzel" atmalarını kullanmalıdır __bridge_transfer, __unsafe_unretainedve __autoreleasing. Kimsenin buna vakti yok. (Ve cidden, okumak daha zor. Bence bellek yönetimini hiç kolaylaştırmadı.)

1
@ H2CO3 cevabınız için teşekkür ederim. Özellikle son cümleye kesinlikle katılmıyorum, ancak bakış
açınıza

Yanıtlar:


180

Tipik

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

ve

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

Şimdi, __bridgeanahtar kelimenin neden orada olduğunu bilmek istiyorsanız , Apple belgelerine bakabilirsiniz . Orada bulacaksın:

__bridge Mülkiyet devri olmaksızın Objective-C ve Core Foundation arasında bir işaretçi aktarır.

__bridge_retainedveya CFBridgingRetainbir Core Foundation işaretçisine bir Objective-C işaretçisini atar ve ayrıca sahipliği size aktarır. Nesnenin sahipliğinden vazgeçmek için CFRelease'i veya ilgili bir işlevi aramaktan sorumlusunuz.

__bridge_transferveya CFBridgingReleaseObjective-C olmayan bir işaretçiyi Objective-C'ye taşır ve sahipliği ARC'ye aktarır. ARC, nesnenin sahipliğinden vazgeçmekten sorumludur.

Bu, yukarıdaki durumlarda, sahipliği değiştirmeden nesneyi yayınladığınız anlamına gelir. Bu, her iki durumda da dizelerin belleğini idare etmekten sorumlu olmayacağınız anlamına gelir.

Ayrıca, herhangi bir nedenle mülkiyeti devretmek istediğiniz durum da olabilir.

Örneğin aşağıdaki pasajı düşünün

- (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
}

böyle bir durumda CFRelease, yayın yaparken sahipliği devrederek bir kaydetmek isteyebilirsiniz .

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

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

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

Mülkiyeti straktarıldı, bu yüzden şimdi ARC devreye girecek ve hafızayı sizin için serbest bırakacak.

Eğer bir yayın yapabiliyorsa etrafındaki diğer Yolda NSString *bir karşı CFStringbir kullanarak __bridge_retainednesneyi sahibi olacak ve açıkça kullanarak bırakın gerekecek, böylece döküm CFRelease.


Sarmak için sahip olabilirsin

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;

Çok teşekkürler, bu pek sezgisel değil, ama senin sayende, alınan ders
Sulfkain

@: küçük soru. öyleyse ARC kullanırsak. ne zaman NSString->CFStringkullanmalıyız __bridge. ama ne zaman CFString->NSStringkullanmalıyız __bride_transfer. ? Ve CFReleaseihtiyacımız olmadığında kullanırsak herhangi bir yan etki . teşekkürler :)
hqt

@hqt, 'kolay' yolu istiyorsanız, evet söyledikleriniz doğru. Ayrıca, bir ekstra CFRelease, programınızı makul bir şekilde çökertmelidir, çünkü uyumsuz tut / bırak işlemiyle sonuçlanacak ve sonunda bir NULLişaretçi bırakacaksınız .
Gabriele Petronella
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.