ฉันกำลังพยายามทำความเข้าใจวิธีที่ถูกต้องในการรับNSStringจากCFStringRefARC หรือไม่? เช่นเดียวกันกับการไปในทิศทางตรงกันข้ามCFStringRefกับNSStringใน ARC?
อะไรคือวิธีที่ถูกต้องในการทำเช่นนี้โดยไม่ทำให้หน่วยความจำรั่วไหล?
ฉันกำลังพยายามทำความเข้าใจวิธีที่ถูกต้องในการรับNSStringจากCFStringRefARC หรือไม่? เช่นเดียวกันกับการไปในทิศทางตรงกันข้าม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_retainedCFRelease
ในการสรุปคุณสามารถมีได้
// 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;