ถึง ARC หรือไม่ไปที่ ARC? ข้อดีข้อเสียคืออะไร? [ปิด]


113

ฉันยังไม่ได้ใช้ ARC เนื่องจากโค้ดส่วนใหญ่ในโปรเจ็กต์ที่ฉันกำลังดำเนินการอยู่นั้นเขียนขึ้นก่อน iOS 5.0

ฉันแค่สงสัยว่าความสะดวกสบายในการไม่เก็บ / ปล่อยด้วยตนเอง (และน่าจะเป็นรหัสที่น่าเชื่อถือกว่าซึ่งเป็นผลมาจาก) มีมากกว่า 'ค่าใช้จ่าย' ในการใช้ ARC หรือไม่? คุณมีประสบการณ์เกี่ยวกับ ARC อย่างไรและคุณจะแนะนำหรือไม่

ดังนั้น:

  • ARC สามารถสร้างประโยชน์ให้กับโครงการได้มากแค่ไหน?
  • ARC มีค่าใช้จ่ายเหมือนการเก็บขยะใน Java หรือไม่?
  • คุณเคยใช้ ARC และถ้าเป็นเช่นนั้นคุณพบมันได้อย่างไร?

ไม่มีการเก็บขยะบน ipad / ios คุณกำลังพูดถึง OS X หรือไม่?
dasblinkenlight

1
ขออภัยฉันใช้คำศัพท์ Java นอกสถานที่ ฉันหมายความว่าด้วย ARC วัตถุสามารถถูกเก็บไว้ในหน่วยความจำได้นานเกินความจำเป็นจากนั้นจึงปล่อยเป็นกลุ่มในกลุ่มการปล่อยอัตโนมัติในภายหลัง เป็นผลจากการที่พวกมันถูกเก็บและปล่อยออกมาพร้อมกับวัตถุอื่น ๆ ในภายหลังเช่นเดียวกับการเก็บขยะของ Java ที่ฉันอ้างถึง
Simon Withington

3
@TenementFunster สำหรับรหัสเดียวกัน (ลบการเรียกให้ปล่อย) ARC จะถือวัตถุไว้ไม่เกินโค้ดที่ไม่ใช่ ARC ในความเป็นจริงมันมักจะปล่อยมันเร็วกว่าที่คุณจะมี มีบางสิ่งที่ค่อนข้างช้ากว่า แต่ก็เร่งรูปแบบทั่วไปมากจนทำให้ผลกระทบด้านประสิทธิภาพลดลง สำหรับรูปแบบทั่วไปจำนวนมาก (การเก็บรักษาวัตถุที่ส่งคืนด้วยการปล่อยอัตโนมัติเป็นต้น) คุณไม่สามารถเขียนด้วยมือได้เร็วเท่าที่ ARC จะทำโดยอัตโนมัติ
Rob Napier

1
เกี่ยวกับการเก็บขยะโปรดดูคำตอบของฉันสำหรับคำถามที่คล้ายกันนี้: อะไรคือความแตกต่างระหว่างการนับอ้างอิงอัตโนมัติของ Objective-C และการรวบรวมขยะ
Brad Larson

คำตอบ:


147

ไม่มีข้อเสีย ใช้มัน. ทำวันนี้ เร็วกว่ารหัสเดิมของคุณ ปลอดภัยกว่ารหัสเดิมของคุณ ง่ายกว่ารหัสเดิมของคุณ ไม่ใช่การเก็บขยะ ไม่มีค่าใช้จ่ายรันไทม์ GC ส่วนแทรกของคอมไพเลอร์จะเก็บรักษาและเผยแพร่ในทุกที่ที่คุณควรมีต่อไป แต่ฉลาดกว่าคุณและสามารถปรับแต่งสิ่งที่ไม่จำเป็นจริงๆได้ (เช่นเดียวกับที่สามารถคลายการวนซ้ำกำจัดตัวแปรชั่วคราวฟังก์ชันอินไลน์ ฯลฯ )

ตกลงตอนนี้ฉันจะบอกคุณเกี่ยวกับข้อเสียเล็ก ๆ :

  • หากคุณเป็นนักพัฒนา ObjC เป็นเวลานานคุณจะกระตุกประมาณหนึ่งสัปดาห์เมื่อคุณเห็นรหัส ARC คุณจะผ่านพ้นเรื่องนี้ไปได้อย่างรวดเร็ว

  • มีความซับซ้อนเล็กน้อย (มาก) ในการเชื่อมโยงกับรหัส Core Foundation มีความซับซ้อนเล็กน้อยในการจัดการกับสิ่งที่ถือว่าidเป็นvoid*. สิ่งต่างๆเช่น C-arrays idสามารถใช้เวลาคิดอีกเล็กน้อยเพื่อให้ทำอย่างถูกต้อง การจัดการ ObjC แบบแฟนซีva_argsอาจทำให้เกิดปัญหาได้เช่นกัน สิ่งส่วนใหญ่ที่เกี่ยวข้องกับคณิตศาสตร์บนตัวชี้ ObjC นั้นยุ่งยากกว่า คุณไม่ควรมีสิ่งนี้มากไม่ว่าในกรณีใด ๆ

  • คุณไม่สามารถใส่idไฟล์struct. สิ่งนี้ค่อนข้างหายาก แต่บางครั้งก็ใช้ในการแพ็คข้อมูล

  • หากคุณไม่ปฏิบัติตามการตั้งชื่อ KVC ที่ถูกต้องและคุณผสมระหว่างรหัส ARC และไม่ใช่ ARC คุณจะมีปัญหาเกี่ยวกับหน่วยความจำ ARC ใช้การตั้งชื่อ KVC เพื่อตัดสินใจเกี่ยวกับการจัดการหน่วยความจำ หากเป็นรหัส ARC ทั้งหมดก็ไม่สำคัญเพราะจะทำให้ "ผิด" เหมือนกันทั้งสองด้าน แต่ถ้าผสม ARC / ไม่ใช่ ARC แสดงว่าไม่ตรงกัน

  • ARC จะรั่วไหลหน่วยความจำในระหว่างการโยนข้อยกเว้นของ ObjC ข้อยกเว้นของ ObjC ควรใกล้เคียงกับการยุติโปรแกรมของคุณ หากคุณพบข้อยกเว้น ObjC จำนวนมากแสดงว่าคุณใช้ไม่ถูกต้อง สามารถแก้ไขได้โดยใช้-fobjc-arc-exceptionsแต่จะมีบทลงโทษที่กล่าวถึงด้านล่าง:

  • ARC จะไม่รั่วไหลของหน่วยความจำในระหว่างข้อยกเว้นของ ObjC หรือ C ++ จะแสดงรหัส ObjC ++ แต่จะต้องเสียค่าใช้จ่ายทั้งเวลาและประสิทธิภาพของพื้นที่ นี่เป็นอีกหนึ่งเหตุผลในการลดการใช้ ObjC ++

  • ARC จะไม่ทำงานเลยบน iPhoneOS 3 หรือ Mac OS X 10.5 หรือรุ่นก่อนหน้า (สิ่งนี้ขัดขวางไม่ให้ฉันใช้ ARC ในหลาย ๆ โครงการ)

  • __weakตัวชี้ทำงานไม่ถูกต้องบน iOS 4 หรือ Mac OS X 10.6 ซึ่งเป็นเรื่องที่น่าเสียดาย แต่ค่อนข้างง่ายในการแก้ไข __weakคำแนะนำนั้นยอดเยี่ยม แต่ไม่ใช่จุดขายอันดับ 1 ของ ARC

สำหรับโค้ด 95% + ARC นั้นยอดเยี่ยมและไม่มีเหตุผลใด ๆ ที่จะหลีกเลี่ยง (หากคุณสามารถจัดการกับข้อ จำกัด เวอร์ชัน OS ได้) สำหรับรหัสที่ไม่ใช่ ARC คุณสามารถส่งผ่านได้-fno-objc-arcต่อแบบทีละไฟล์ Xcode ทำให้สิ่งนี้ยากกว่าที่ควรจะเป็นในทางปฏิบัติ คุณควรย้ายโค้ดที่ไม่ใช่ ARC ไปไว้ใน xcodeproj แยกต่างหากเพื่อให้ง่ายขึ้น

โดยสรุปให้เปลี่ยนไปใช้ ARC โดยเร็วที่สุดและอย่ามองย้อนกลับไป


แก้ไข

ฉันได้เห็นความคิดเห็นสองสามข้อในบรรทัด "การใช้ ARC ไม่สามารถทดแทนการรู้กฎการจัดการหน่วยความจำ Cocoa ได้" นี่เป็นความจริงส่วนใหญ่ แต่สิ่งสำคัญคือต้องเข้าใจว่าทำไมและทำไมถึงไม่ทำ ขั้นแรกหากโค้ดทั้งหมดของคุณใช้ ARC และคุณละเมิด Three Magic Wordsทั่วทุกแห่งคุณจะยังไม่มีปัญหา น่าตกใจที่จะพูด แต่คุณไปแล้ว ARC อาจเก็บรักษาบางสิ่งที่คุณไม่ได้ตั้งใจที่จะรักษาไว้ แต่มันก็จะปล่อยมันออกมาเช่นกันดังนั้นมันก็ไม่สำคัญ ถ้าฉันสอนคลาสใหม่ใน Cocoa วันนี้ฉันอาจจะใช้เวลาไม่เกินห้านาทีกับกฎการจัดการหน่วยความจำจริงและฉันอาจจะพูดถึงกฎการตั้งชื่อการจัดการหน่วยความจำเท่านั้นในขณะที่พูดคุยเกี่ยวกับการตั้งชื่อ KVC ด้วย ARC ฉันเชื่อว่าคุณสามารถเป็นโปรแกรมเมอร์เริ่มต้นที่ดีได้โดยไม่ต้องเรียนรู้กฎการจัดการหน่วยความจำเลย

แต่คุณไม่สามารถเป็นโปรแกรมเมอร์ระดับกลางที่ดีได้ คุณจำเป็นต้องรู้กฎเพื่อที่จะเชื่อมโยงกับ Core Foundation ได้อย่างถูกต้องและโปรแกรมเมอร์ระดับกลางทุกคนจำเป็นต้องจัดการกับ CF ในบางจุด และคุณต้องรู้กฎสำหรับรหัสผสม ARC / MRC และคุณจำเป็นต้องรู้กฎเมื่อคุณเริ่มยุ่งกับvoid*คำแนะนำid(ซึ่งคุณจะต้องดำเนินการ KVO อย่างถูกต้องต่อไป) และบล็อก ... การจัดการหน่วยความจำบล็อกเป็นเรื่องแปลก

ดังนั้นประเด็นของฉันก็คือการจัดการหน่วยความจำพื้นฐานยังคงมีความสำคัญ แต่ที่ซึ่งฉันเคยใช้เวลาอย่างมีนัยสำคัญในการระบุและทบทวนกฎสำหรับโปรแกรมเมอร์ใหม่โดย ARC กำลังกลายเป็นหัวข้อขั้นสูงมากขึ้น objc_retain()ฉันอยากจะได้รับการพัฒนาใหม่คิดในแง่ของกราฟวัตถุมากกว่าการเติมหัวของพวกเขาด้วยการโทรพื้นฐานเพื่อ


3
สิ่งหนึ่งที่ต้องระวังให้มาก (ในที่ไม่ใช่ ARC เช่นกัน แต่มีมากกว่านั้นใน ARC เพราะตอนนี้มองไม่เห็น) คือการรักษาวัฏจักร คำแนะนำของฉันที่นี่คือ 1) หากคุณพบว่าตัวเองเก็บบล็อก objc ไว้เป็นตัวแปรอินสแตนซ์ลองพิจารณาดูให้ดีเพื่อดูว่าสามารถจับวัตถุที่เป็นไอวาร์ได้หรือไม่แม้โดยทางอ้อม 2) ออกแบบกราฟวัตถุของคุณจริงๆแทนที่จะปล่อยให้มันเกิดขึ้น คุณต้องรู้ว่าอะไรเป็นเจ้าของถ้าคุณต้องการเขียนโค้ดที่ดี 3) ใช้ heapshots: friday.com/bbum/2010/10/17/…
Catfish_Man

1
@Catfish_Man ทุกจุดดี. การรักษาลูปเป็นปัญหาเสมอมา คำแนะนำใหม่ของ Apple ตรงตามที่คุณพูดใน # 2 เราจำเป็นต้องคิดเกี่ยวกับกราฟออบเจ็กต์มากกว่าที่จะเก็บและปล่อย # 1 เป็นปัญหาร้ายแรงเกี่ยวกับบล็อกและหนึ่งในหลายเหตุผลที่ฉันพบว่าบล็อกเป็นพรแบบผสมผสานที่ควรเข้าหาด้วยความระมัดระวัง
Rob Napier

2
มีข้อเสียร้ายแรงประการหนึ่งที่ไม่ได้กล่าวถึง: ความเข้ากันได้ข้ามกัน สำหรับพวกเราวิญญาณที่กล้าหาญและโง่เขลาที่ต้องเผชิญกับดินแดนรกร้างที่เรียกว่าการเขียนโปรแกรมข้ามแพลตฟอร์มนั้น ARC ไม่ใช่ตัวเลือกอย่างน้อยก็จนกว่า GNU จะขยายตามรันไทม์ ObjC และคุณสมบัติคอมไพเลอร์ของพวกเขาอีกครั้ง (พวกเขากล่าวว่ามีมากกว่านี้)
Rabbit

2
คุณสามารถใช้ ARC ได้ยกเว้นว่าคุณต้องรองรับอุปกรณ์ iOS 3.x BTW ตรวจสอบให้แน่ใจว่าได้ใช้ Xcode เพื่อทำการเปลี่ยนแปลง (แก้ไข> Refactor> แปลงเป็น Objective-C ARC) ในระหว่างกระบวนการ Xcode จะทำการตรวจสอบความถูกต้องจำนวนมากเพื่อให้แน่ใจว่าโค้ดของคุณใช้งานได้และค้นหารหัสใด ๆ ที่ละเมิดหลักเกณฑ์การออกแบบเหล่านั้น
ZhangChn

1
ยอดเยี่ยม .. ตอบแบบชี้ ๆ . นั่นคืออันดับที่ 100 จากฉัน รวมตัวกันเป็นศตวรรษ;)
Ajay Sharma

20

คำตอบทางเทคนิคที่ดีและดีกว่าของฉันจะมา แต่ต่อไปนี้:

  • ARC! = เก็บขยะ ไม่มีการลงโทษเวลาทำงานจะทำในเวลารวบรวม
  • ARC ยัง! = ปล่อยทุกอย่างอัตโนมัติตามที่คุณแนะนำในความคิดเห็นของคุณ อ่านเอกสาร
  • มันน่ากลัวเมื่อคุณตระหนักถึงการจัดการการอ้างอิงเท่าใดคู่มือคุณถูกทำ
  • ใช้มัน!
  • ข้อเสียเปรียบประการหนึ่ง - การรักษารหัสเก่าที่ไม่ใช่อาร์กจะกลายเป็นเรื่องที่น่าเบื่ออย่างมาก

ใช่นั่นเป็นเหตุผลที่ฉันไม่ได้ใช้จนถึงตอนนี้ฉันไม่แน่ใจว่าฉันสามารถทนต่อการแปลงรหัสที่มีอยู่แล้วจำนวนมากของเราได้ ... ฉันจะลองใช้ในโครงการต่อไป ขอบคุณสำหรับคำตอบ :)
Simon Withington

ไม่ใช่ว่าการรักษารหัสเดิมจะยากขึ้น แต่ความคาดหวังของคุณเปลี่ยนไป ดังนั้นจึงไม่ยุติธรรมเลยที่จะตำหนิ ARC ที่ทำให้ชีวิตง่ายขึ้น Xcode ทำให้ง่ายต่อการแปลงรหัสเก่าของคุณเป็น ARC เมื่อคุณพร้อม แต่เห็นได้ชัดว่าคุณไม่สามารถใช้งานได้หากคุณยังต้องรองรับ iOS เวอร์ชันเก่า
Caleb

1
@Caleb ฉันไม่ได้โทษ ARC มันเป็นเพียงข้อเสียเดียวที่ฉันเห็นจนถึงตอนนี้ - มันทำให้ฉันเน่าเสียในพื้นที่ของโครงการเดียว
jrturton

ใช่; ฉันไม่ได้ระบุว่าเป็นปัญหา แต่มีปัญหาเล็กน้อยในการออกจากแนวปฏิบัติในการจัดการหน่วยความจำเมื่อคุณต้องสลับระหว่างโค้ดเบส บางโครงการของฉันทำงานบน 10.4 ดังนั้นฉันยังคงทำงาน Objective-C 1.0 จำนวนมาก (ดังนั้นจึงไม่มี @synthesize นับประสา ARC) แต่คุณคุ้นเคยกับการเปลี่ยนโหมดได้ดี
Rob Napier

@jrturton ฉันควรจะทำให้ชัดเจนมากขึ้นว่าฉันเขียนว่าเพื่อประโยชน์ของ OP และผู้อ่านในอนาคตที่อาจไม่สนใจสิ่งที่ ARC ทำ ฉันรู้ว่าคุณหมายถึงอะไรไม่ต้องการให้ใครสรุปข้อสรุปที่ผิดพลาดว่าการผสมรหัส ARC และไม่ใช่ ARC ทำให้เกิดปัญหา
Caleb

16

ARC สามารถสร้างประโยชน์ให้กับโครงการได้มากแค่ไหน?

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

การเก็บขยะ 'มีค่าใช้จ่าย' เท่าไหร่?

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

คุณเคยใช้ ARC และถ้าเป็นเช่นนั้นคุณพบมันได้อย่างไร?

เป็นเรื่องที่น่าสับสนเล็กน้อยหากคุณใช้ในการอ้างอิงการนับ แต่นั่นเป็นเพียงเรื่องของการทำความคุ้นเคยและเรียนรู้ที่จะไว้วางใจว่าคอมไพเลอร์จะทำสิ่งที่ถูกต้องจริงๆ รู้สึกเหมือนความต่อเนื่องของการเปลี่ยนแปลงคุณสมบัติที่มาพร้อมกับ Objective-C 2.0 ซึ่งเป็นอีกก้าวสำคัญในการทำให้การจัดการหน่วยความจำง่ายขึ้น หากไม่มีการเรียกการจัดการหน่วยความจำด้วยตนเองรหัสของคุณจะสั้นลงและอ่านง่ายขึ้นเล็กน้อย

ปัญหาเดียวของ ARC คือไม่รองรับ iOS เวอร์ชันเก่าดังนั้นคุณต้องคำนึงถึงสิ่งนั้นก่อนที่จะตัดสินใจนำมาใช้


1
มีคำตอบที่ดีกว่าที่ฉันพูดถึง!
jrturton

1
ใช่คำตอบที่ดี ดังนั้นจึงไม่มีข้อเสียเปรียบสำหรับ ARC นอกเหนือจากการเรียนรู้ที่จะไว้วางใจว่ามันใช้งานได้จริงหรือ? ดูเหมือนดีเกินไปที่จะเป็นจริงในกรณีนั้น?
Simon Withington

4

ฉันคิดว่า ARC เป็นความคิดที่ดี เมื่อเทียบกับ GC คุณสามารถมีเค้กและทานได้เช่นกัน ฉันมักจะเชื่อว่า MRC กำหนด 'วินัย' อันล้ำค่าต่อการจัดการหน่วยความจำที่ทุกคนจะได้รับประโยชน์จากการมี แต่ฉันก็ยอมรับเช่นกันว่าปัญหาที่แท้จริงที่ต้องระวังคือ Object Ownership และ Object Graphs (ตามที่หลาย ๆ คนชี้ให้เห็น) ไม่ใช่จำนวนการอ้างอิงระดับต่ำต่อ se

สรุปได้ว่า ARC ไม่ใช่ทางผ่านฟรีที่จะไม่สนใจเรื่องความจำ เป็นเครื่องมือที่ช่วยให้มนุษย์หลีกเลี่ยงงานซ้ำ ๆ ซึ่งก่อให้เกิดความเครียดและมีแนวโน้มที่จะเกิดข้อผิดพลาดดังนั้นจึงควรมอบหมายให้กับเครื่อง (คอมไพเลอร์ในกรณีนี้)

ที่กล่าวว่าฉันเป็นช่างฝีมือเป็นการส่วนตัวและยังไม่ได้ทำการเปลี่ยนแปลง ฉันเพิ่งเริ่มใช้ Git ...

อัปเดต:ดังนั้นฉันจึงย้ายเกมทั้งหมดของฉันรวมไลบรารี gl และไม่มีปัญหาใด ๆ (ยกเว้นกับผู้ช่วยการย้ายข้อมูลใน Xcode 4.2) หากคุณกำลังเริ่มโครงการใหม่ไปเลย


2

ฉันเคยใช้มันในโครงการ (ขนาดเล็ก) สองสามโครงการและฉันมี แต่ประสบการณ์ที่ดีทั้งประสิทธิภาพและความน่าเชื่อถือที่ชาญฉลาด

ข้อควรระวังเล็กน้อยประการหนึ่งคือคุณต้องเรียนรู้ do: s และ don't: s ของการอ้างอิงที่อ่อนแอเพื่อไม่ให้เกิดการอ้างอิงใด ๆ หากคุณเข้ารหัส UI ด้วยตัวเองนักออกแบบมักจะทำงานได้ดี โดยอัตโนมัติหากคุณตั้งค่า GUI โดยใช้มัน


2

ข้อเสียเพียงอย่างเดียวที่ฉันพบคือหากคุณใช้ไลบรารีที่มีฟังก์ชันและข้อมูล CoreFoundation จำนวนมาก ใน MRC คุณไม่จำเป็นต้องกังวลเกี่ยวกับการใช้ a CFStringRefแทนNSString*ไฟล์. ใน ARC คุณต้องระบุว่าทั้งสองโต้ตอบกันอย่างไร (บริดจ์พื้นฐานหรือไม่ปล่อยวัตถุ CoreFoundation และย้ายไปที่ ARC สร้างวัตถุ Cocoa เป็นวัตถุที่เก็บรักษา +1 CoreFoundation หรือไม่) นอกจากนี้บน OS X จะมีให้ใช้งานบน 64 เท่านั้น รหัสบิต (แม้ว่าฉันจะมีส่วนหัวที่ใช้งานได้ ... )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.