ฉันกำลังพยายามทำความเข้าใจวิธีที่ถูกต้องในการรับNSString
จากCFStringRef
ARC หรือไม่? เช่นเดียวกันกับการไปในทิศทางตรงกันข้ามCFStringRef
กับNSString
ใน ARC?
อะไรคือวิธีที่ถูกต้องในการทำเช่นนี้โดยไม่ทำให้หน่วยความจำรั่วไหล?
ฉันกำลังพยายามทำความเข้าใจวิธีที่ถูกต้องในการรับNSString
จากCFStringRef
ARC หรือไม่? เช่นเดียวกันกับการไปในทิศทางตรงกันข้ามCFStringRef
กับNSString
ใน ARC?
อะไรคือวิธีที่ถูกต้องในการทำเช่นนี้โดยไม่ทำให้หน่วยความจำรั่วไหล?
retain
ไอเอ็นจีและrelease
ไอเอ็นจีวัตถุที่เราจะต้องตอนนี้ใช้ปลดเปลื้อง "สวย" เหมือน__bridge_transfer
, และ__unsafe_unretained
__autoreleasing
ไม่มีใครไม่มีเวลาสำหรับสิ่งนั้น (และอย่างจริงจังมันอ่านยากกว่าในความคิดของฉันมันไม่ได้อำนวยความสะดวกในการจัดการหน่วยความ
คำตอบ:
โดยปกติ
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
และ
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
ตอนนี้ถ้าคุณต้องการที่จะรู้ว่าทำไม__bridge
คำหลักคือมีคุณสามารถอ้างถึงเอกสารที่แอปเปิ้ล คุณจะพบ:
__bridge
ถ่ายโอนตัวชี้ระหว่าง Objective-C และ Core Foundation โดยไม่มีการโอนความเป็นเจ้าของ
__bridge_retained
หรือCFBridgingRetain
ร่ายตัวชี้ Objective-C ไปยังตัวชี้ Core Foundation และยังโอนความเป็นเจ้าของให้คุณ คุณต้องรับผิดชอบในการเรียกใช้ CFRelease หรือฟังก์ชันที่เกี่ยวข้องเพื่อสละความเป็นเจ้าของวัตถุ
__bridge_transfer
หรือCFBridgingRelease
ย้ายตัวชี้ที่ไม่ใช่ Objective-C ไปยัง Objective-C และยังโอนความเป็นเจ้าของไปยัง ARC ARC มีหน้าที่ในการสละสิทธิ์ความเป็นเจ้าของวัตถุ
ซึ่งหมายความว่าในกรณีข้างต้นคุณกำลังแคสต์วัตถุโดยไม่เปลี่ยนความเป็นเจ้าของ นี่หมายความว่าไม่ว่าในกรณีใดคุณจะต้องรับผิดชอบในการจัดการหน่วยความจำของสตริง
นอกจากนี้ยังอาจมีบางกรณีที่คุณต้องการโอนกรรมสิทธิ์ด้วยเหตุผลบางประการ
ตัวอย่างเช่นพิจารณาตัวอย่างต่อไปนี้
- (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
}
ในกรณีนี้คุณอาจต้องการบันทึกCFRelease
โดยการโอนความเป็นเจ้าของเมื่อแคสต์
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
NSString * aNSString = (NSString *)CFBridgingRelease(str);
NSLog(@"%@", aNSString);
}
กรรมสิทธิ์ของ str
แล้วตอนนี้ ARC จะเริ่มต้นและปล่อยหน่วยความจำให้คุณ
เกี่ยวกับวิธีอื่น ๆ ที่คุณสามารถโยนNSString *
ไปCFString
ใช้หล่อเพื่อที่คุณจะเป็นเจ้าของวัตถุและคุณจะต้องชัดเจนปล่อยมันโดยใช้__bridge_retained
CFRelease
ในการสรุปคุณสามารถมีได้
// 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
__bridge
แต่เมื่อเราควรจะใช้CFString->NSString
__bride_transfer
เหรอ? และผลข้างเคียงใด ๆ หากเราใช้CFRelease
เมื่อเราไม่ต้องการด้วย ขอบคุณ :)
CFRelease
ควรทำให้โปรแกรมของคุณขัดข้องพอสมควรเนื่องจากคุณจะจบลงด้วยการดำเนินการเก็บ / รีลีสที่ไม่ตรงกันในที่สุดก็ปล่อยตัวNULL
ชี้
CFStringRef foo (__bridge CFStringRef)theNSString;
และNSString *bar = (__bridge NSString *)theCFString;