ARC และ bridged cast


166

ด้วย ARC ฉันไม่สามารถเลือกใช้อีกต่อCGColorRefไปidได้ ฉันเรียนรู้ว่าฉันต้องทำนักแสดงที่เชื่อมโยง ตามเอกสารดังกราว :

หล่อสะพานเป็น C- โยนสไตล์ข้อเขียนกับหนึ่งในสามคำ:

(__bridge T) opTปลดเปลื้องตัวถูกดำเนินการประเภทปลายทาง หากT เป็นประเภทตัวชี้วัตถุที่คงไว้ได้นั้นopจะต้องมีประเภทตัวชี้ที่ไม่สามารถเก็บรักษาได้ ถ้าTเป็นประเภทพอยน์เตอร์ที่ไม่สามารถเก็บถาวรได้ op จะต้องมีประเภทพอยน์เตอร์ของวัตถุที่คงอยู่ได้ มิฉะนั้นนักแสดงจะหล่อขึ้นมา ไม่มีการถ่ายโอนความเป็นเจ้าของและ ARC จะไม่มีการดำเนินการเก็บรักษาไว้

(__bridge_retained T) opปลดเปลื้องตัวถูกดำเนินการซึ่งจะต้องมีประเภทตัวชี้วัตถุที่เก็บรักษาไว้กับประเภทปลายทางซึ่งจะต้องเป็นประเภทตัวชี้ที่ไม่สามารถเก็บรักษาได้ ARC จะรักษาค่าไว้โดยขึ้นอยู่กับการปรับค่าตามปกติตามปกติและผู้รับจะรับผิดชอบในการปรับสมดุล +1 นั้น

(__bridge_transfer T) opปลดเปลื้องตัวถูกดำเนินการซึ่งจะต้องมีประเภทตัวชี้ที่ไม่สามารถเก็บรักษาไว้กับประเภทปลายทางซึ่งจะต้องเป็นประเภทตัวชี้วัตถุที่รักษาได้ ARC จะปล่อยค่าในตอนท้ายของนิพจน์แบบปิดล้อมซึ่งขึ้นอยู่กับการเพิ่มประสิทธิภาพตามปกติของค่าท้องถิ่น

การปลดเปลื้องเหล่านี้จำเป็นต้องมีเพื่อถ่ายโอนวัตถุเข้าและออกจากการควบคุม ARC; ดูเหตุผลในส่วนการแปลงของพอยน์เตอร์พอยน์เตอร์ที่เก็บได้

การใช้__bridge_retainedหรือ__bridge_transferโยนเพื่อโน้มน้าวใจ ARC ให้ปล่อยการเก็บหรือปล่อยที่ไม่สมดุลตามลำดับเป็นรูปแบบที่ไม่ดี

ในสถานการณ์แบบใดฉันจะใช้แต่ละสถานการณ์

ตัวอย่างเช่นCAGradientLayerมีcolorsคุณสมบัติที่รับอาร์เรย์ของCGColorRefs ฉันเดาว่าฉันควรใช้__brigeที่นี่ แต่ทำไมฉันควร (หรือไม่ควร) ไม่ชัดเจน


17
คุณได้ดูการประชุม WWDC 2011 323 หรือยัง นั่นอธิบาย ARC ดีกว่าที่ฉันจะทำได้ที่นี่ ครอบคลุมรายละเอียดทั้งหมดตั้งแต่ต้นจนจบ ต้องดูเซสชันสำหรับนักพัฒนา Mac / iOS ทุกคน
rbrown

สิ่งนี้อาจช่วยได้เช่น: stackoverflow.com/questions/14352494/…
Ewan Mellor

ลิงก์ไปยังเซสชันของ WWDC ไม่น่าแปลกใจที่จะค้นพบ: developer.apple.com/videos/play/wwdc2011/323 - บิตที่เกี่ยวข้องอยู่ที่ 23:15
Daniel

คำตอบ:


215

ฉันเห็นด้วยว่าคำอธิบายนั้นสร้างความสับสน ตั้งแต่ฉันเพิ่งจับพวกเขาฉันจะพยายามสรุป:

  • (__bridge_transfer <NSType>) opหรือมิฉะนั้นCFBridgingRelease(op)จะใช้เพื่อใช้จำนวนที่เก็บไว้ของการCFTypeRefโอนย้ายไปยัง ARC นี่อาจเป็นตัวแทนของid someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) opหรือCFBridgingRetain(op)จะใช้เพื่อส่งมอบให้NSObjectกับ CF-land ในขณะที่ให้ +1 เก็บไว้นับ คุณควรจะจัดการให้คุณสร้างด้วยวิธีนี้เช่นเดียวกับคุณจะจัดการผลมาจากการCFTypeRef CFStringCreateCopy()นี่อาจเป็นตัวแทนของCFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridgeเพียงปลดเปลื้องระหว่างตัวชี้ที่ดินและวัตถุประสงค์ -C วัตถุที่ดิน หากคุณไม่มีความชอบที่จะใช้การแปลงข้างต้นให้ใช้สิ่งนี้

บางทีนี่อาจเป็นประโยชน์ ตัวฉันเองฉันชอบCFBridging…มาโครมากกว่าสคริปธรรมดา


จำนวนของออบเจ็กต์ยังคงเพิ่มขึ้นโดย arc 1 เมื่อคุณใช้ __bridge_transfer หรือไม่ มิฉะนั้นจะดูเหมือนว่าช่วงเวลาที่ CFRelease () ถูกเรียกว่าวัตถุนั้นหายไปและชี้ไปที่สิ่งใด ในทำนองเดียวกันเมื่อคุณใช้ __bridge_retain ARC จะลดจำนวนการเก็บรักษาของ op ด้วย 1 หรือไม่? ดูเหมือนว่าวัตถุจะไม่ถูกปล่อยอย่างถูกต้อง
Tony

2
เมื่ออยู่ในดินแดน ARC คุณไม่คิดว่าจะเก็บไว้นับได้อีกต่อไปมีเพียงการอ้างอิงที่แข็งแกร่งและอ่อนแอเท่านั้น
monkeydom

4
ใช่ถ้าคุณอยู่ในดินแดนโค้งเท่านั้นที่แข็งแกร่ง / อ่อนแอจะเพียงพอ แต่เมื่อคุณเปลี่ยนวัตถุระหว่างสภาพแวดล้อมอาร์คและที่ไม่ใช่อาร์คคุณยังคงต้องคิดเกี่ยวกับผลกระทบที่นับไว้ภายใต้ประทุน
Tony

3
ไม่ได้จริงๆ คุณต้องคิดถึงการเข้าและออกจากดินแดน ARC และนี่คือการจดจำการบันทึกอัตโนมัติที่น่าจดจำ (น่าสนใจพอ: ARC แก้ไขรูปแบบทั่วไปเช่นการนำวัตถุออกจากพจนานุกรมแล้วนำออกก่อนที่จะใช้ ฯลฯ )
monkeydom

3
การใช้เครื่องมือวิเคราะห์ (shift + command + B) สามารถช่วยในการแก้ไขข้อสงสัยดังกล่าวได้เนื่องจากมันจะบอกคุณในภาษาธรรมชาติหากรหัสปัจจุบันกำลังรั่วหน่วยความจำ ถ้าเป็นเช่นนั้นคุณอาจกำลังใช้คาสต์การรักษาในขณะที่คุณควรใช้แคสต์ที่ไม่ได้ทำการยึด หากตัววิเคราะห์ไม่เตือนคุณเกี่ยวกับสิ่งใด ๆ ในบรรทัดรหัสนั้นคุณอาจทำงานได้ดีกับรหัสปัจจุบัน
Fabio Napodano

55

ฉันพบคำอธิบายอื่นในเอกสารประกอบ iOS ที่ฉันคิดว่าเข้าใจง่ายกว่า:

  • __bridge ถ่ายโอนตัวชี้ระหว่าง Objective-C และ Core Foundation โดยไม่ต้องโอนกรรมสิทธิ์

  • __bridge_retained (CFBridgingRetain)ส่งคำสั่งแบบObjective-Cไปยังตัวชี้Core Foundationและโอนความเป็นเจ้าของให้คุณ

    คุณมีหน้าที่รับผิดชอบในการเรียก CFRelease หรือฟังก์ชั่นที่เกี่ยวข้องเพื่อสละสิทธิ์การเป็นเจ้าของวัตถุ

  • __bridge_transfer (CFBridgingRelease) ย้าย ตัวชี้ที่ไม่ใช่ Objective-C ไปยัง Objective-Cและโอนความเป็นเจ้าของไปยัง ARC

    ARC รับผิดชอบการยกเลิกการเป็นเจ้าของวัตถุ

ที่มา: ประเภท Bridged ปลอดการโทร


33

ในกรณีเฉพาะนี้หากคุณใช้ iOS iOS แนะนำให้ใช้ UIColor และ-CGColorวิธีการส่ง CGColorRef กลับสู่colorsNSArray ในบันทึกย่อประจำรุ่นการเปลี่ยนเป็น ARCภายใต้หัวข้อ "คอมไพเลอร์จัดการ CF วัตถุที่ส่งคืนจากวิธีการโกโก้" แสดงว่าใช้วิธีเช่น-CGColorที่ส่งคืนวัตถุรากฐานหลักจะได้รับการจัดการอย่างเหมาะสมโดยอัตโนมัติโดยคอมไพเลอร์

ดังนั้นพวกเขาแนะนำให้ใช้รหัสดังนี้:

CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

โปรดทราบว่า ณ ตอนนี้โค้ดตัวอย่างของ Apple ไม่มีรหัส cast (id) ที่ฉันมีอยู่ด้านบนซึ่งยังจำเป็นต้องหลีกเลี่ยงข้อผิดพลาดของคอมไพเลอร์


คุณสามารถหนีไปได้ด้วยการส่งวัตถุแรกไปยัง (id) แทนวัตถุทั้งหมดหากคุณต้องการ
Philippe Sabourin

1
คำถามนี้ถามเกี่ยวกับการส่งกับ ARC โดยที่รหัสที่คุณวางไม่ถูกกฎหมาย
Joey Hagedorn

11
@JoeyHagedorn - บางทีคุณอาจพลาดการอ้างอิงไปยังเอกสาร ARC ของฉันในประโยคแรกของคำตอบของฉัน แต่ไม่เพียงแค่นี้ถูกต้องภายใต้ ARC มันเป็นวิธีที่แนะนำสำหรับการให้การอ้างอิง CGColorRef ใน NSArrays จากวิธีการแปลง UIColor เหล่านี้ ฉันและคนอื่น ๆ ใช้รหัสที่แน่นอนนี้ภายในแอปพลิเคชันที่เปิดใช้งาน ARC การร่ายไปยัง (id) ทันทีจากวิธีการที่ส่งกลับวัตถุ Core Foundation เชื่อมโยงวัตถุนั้นกับ ARC โดยอัตโนมัติ
แบรด Larson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.