Sto cercando di capire il modo corretto di ottenere un NSString
da un CFStringRef
in ARC? Lo stesso per andare nella direzione opposta, CFStringRef
a NSString
in ARC?
Qual è il modo corretto per farlo senza creare perdite di memoria?
Sto cercando di capire il modo corretto di ottenere un NSString
da un CFStringRef
in ARC? Lo stesso per andare nella direzione opposta, CFStringRef
a NSString
in ARC?
Qual è il modo corretto per farlo senza creare perdite di memoria?
retain
e release
rimuovendo oggetti, dobbiamo ora usare cast "belli" come __bridge_transfer
, __unsafe_unretained
e __autoreleasing
. Nessuno non ha tempo per questo. (E seriamente, è più difficile da leggere. Secondo me, non ha facilitato affatto la gestione della memoria.)
Risposte:
Tipicamente
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
e
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Ora, se vuoi sapere perché c'è la __bridge
parola chiave, puoi fare riferimento alla documentazione di Apple . Lì troverai:
__bridge
trasferisce un puntatore tra Objective-C e Core Foundation senza trasferimento di proprietà.
__bridge_retained
oppureCFBridgingRetain
lancia un puntatore Objective-C a un puntatore Core Foundation e trasferisce anche la proprietà a te. Sei responsabile di chiamare CFRelease o una funzione correlata per rinunciare alla proprietà dell'oggetto.
__bridge_transfer
oCFBridgingRelease
sposta un puntatore non-Objective-C su Objective-C e trasferisce anche la proprietà ad ARC. ARC è responsabile della rinuncia alla proprietà dell'oggetto.
Ciò significa che nei casi sopra si esegue il casting dell'oggetto senza modificare la proprietà. Ciò implica che in nessuno dei due casi sarai responsabile della gestione della memoria delle stringhe.
Potrebbe anche esserci il caso in cui desideri trasferire la proprietà per qualche motivo.
Ad esempio, considera il seguente frammento
- (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 tal caso potresti voler salvare un CFRelease
trasferendo la proprietà durante la trasmissione.
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
NSString * aNSString = (NSString *)CFBridgingRelease(str);
NSLog(@"%@", aNSString);
}
La proprietà di str
è stata trasferita, quindi ora ARC entrerà in azione e rilascerà la memoria per te.
Al contrario, puoi lanciare un NSString *
a CFString
usando un __bridge_retained
cast, in modo da essere proprietario dell'oggetto e dovrai rilasciarlo esplicitamente usando CFRelease
.
Per concludere puoi avere
// 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`
// 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;
NSString->CFString
, dovremmo usare __bridge
. ma quando CFString->NSString
, dovremmo usare __bride_transfer
. ? E qualsiasi effetto collaterale, se lo usiamo CFRelease
quando non ne abbiamo bisogno. grazie :)
CFRelease
dovrebbe ragionevolmente mandare in crash il tuo programma, dal momento che finirai con un'operazione di conservazione / rilascio non corrispondente, rilasciando eventualmente un NULL
puntatore.
CFStringRef foo (__bridge CFStringRef)theNSString;
eNSString *bar = (__bridge NSString *)theCFString;