ควรแทนที่ deinit เพื่อลบผู้สังเกตการณ์ใน Swift หรือไม่

เพื่อนร่วมทีมเขียนโค้ดเช่น

deinit {
    NotificationCenter.default.removeObserver(self)
}

ฉันแสดงความคิดเห็นให้ลบสิ่งนี้ออกเนื่องจากผู้สังเกตการณ์ได้รับการดูแลจากกรอบงานแล้ว เพื่อนร่วมทีมต้องการเก็บรหัสนี้ไว้หากไม่มีผลข้างเคียง ตอนนี้แม้ว่าเราจะเก็บโค้ดด้านบนนี้ไว้ แต่ก็มีผลข้างเคียงหรือไม่?

ฉันควรโทร super.deinit() ภายใน deinit ด้วยหรือไม่


person Sazzad Hissain Khan    schedule 24.02.2020    source แหล่งที่มา
comment
คุณกำลังถามว่าควรแทนที่ deinit โดยทั่วไปหรือไม่ (ตามที่ระบุไว้ในชื่อเรื่อง) หรือควรแทนที่เพื่อลบผู้สังเกตการณ์ออกหรือไม่   -  person Martin R    schedule 24.02.2020
comment
@MartinR เปลี่ยนชื่อ   -  person Sazzad Hissain Khan    schedule 24.02.2020
comment
เปรียบเทียบ stackoverflow.com/q/25069480/1187415 และ stackoverflow.com/q/53394779/1187415   -  person Martin R    schedule 24.02.2020
comment
@MartinR คำตอบของโพสต์ที่ 1 ย้อนหลังไป 6 ปี (ฉันได้ยินมาว่ามีการเปลี่ยนแปลงบางอย่างใน ARC) และคำตอบของโพสต์ที่ 2 ไม่ได้ชี้ถึงปัญหา   -  person Sazzad Hissain Khan    schedule 24.02.2020


คำตอบ (2)


ใน iOS 9 คุณไม่จำเป็นต้องลบผู้สังเกตการณ์ด้วยตัวเอง หากคุณไม่ได้ใช้ผู้สังเกตการณ์แบบบล็อก ระบบจะทำเพื่อคุณ เนื่องจากจะใช้การอ้างอิงแบบ Zeroing-Weak สำหรับผู้สังเกตการณ์ ในจุดที่สามารถทำได้

หากผู้สังเกตการณ์สามารถจัดเก็บเป็นการอ้างอิงที่อ่อนแอเป็นศูนย์ได้ หน่วยเก็บข้อมูลพื้นฐานจะจัดเก็บผู้สังเกตการณ์เป็นการอ้างอิงที่อ่อนแอเป็นศูนย์ หรืออีกทางหนึ่งหากไม่สามารถจัดเก็บวัตถุอย่างอ่อนแอได้ (นั่นคือ มีกลไกการเก็บรักษา/เผยแพร่แบบกำหนดเองที่จะป้องกันรันไทม์ จากความสามารถในการจัดเก็บวัตถุอย่างอ่อน) มันจะจัดเก็บวัตถุเป็นการอ้างอิงค่าศูนย์ที่ไม่อ่อนแอ ซึ่งหมายความว่าผู้สังเกตการณ์ไม่จำเป็นต้องยกเลิกการลงทะเบียนในวิธีการจัดสรรคืน

ผู้สังเกตการณ์ที่บล็อกโดยใช้เมธอด -[NSNotificationCenter addObserverForName: object: Queue:usingBlock] ยังคงจำเป็นต้องยกเลิกการลงทะเบียนเมื่อไม่ได้ใช้งานอีกต่อไป เนื่องจากระบบยังคงมีการอ้างอิงที่ชัดเจนถึงผู้สังเกตการณ์เหล่านี้

เอกสาร Apple

และสำหรับ super.deinit() apple พูดว่า

ตัวดีการเตรียมใช้งานจะถูกเรียกโดยอัตโนมัติ ก่อนการจัดสรรอินสแตนซ์จะเกิดขึ้น คุณไม่ได้รับอนุญาตให้เรียกโปรแกรม deinitializer ด้วยตัวเอง deinitializers ของ Superclass ได้รับการสืบทอดโดยคลาสย่อยของมัน และ deinitializers ของ superclass จะถูกเรียกโดยอัตโนมัติเมื่อสิ้นสุดการใช้ deinitializer ของคลาสย่อย deinitializers ของ Superclass จะถูกเรียกเสมอ แม้ว่าคลาสย่อยจะไม่ได้จัดเตรียมตัว deinitializer ของตัวเองไว้ก็ตาม

เอกสาร Swift

person Jawad Ali    schedule 24.02.2020

ใช่ การแทนที่นั้นถูกต้อง

deinit()

ตามที่ระบุไว้ในความคิดเห็น ไม่ต้องเรียกซุปเปอร์ ฉันยืนยันสิ่งนี้ในเอกสารของ Apple

การทำความสะอาดอย่างชัดเจนเป็นความคิดที่ดี โดยเฉพาะอย่างยิ่งเมื่อพูดถึงเธรด การแจ้งเตือน และตัวจับเวลา

person Woodstock    schedule 24.02.2020
comment
super.deinit()ถูกเรียกโดยนัยใน Swift คุณ ไม่สามารถ เรียกได้อย่างชัดเจน: “ข้อผิดพลาด: ไม่สามารถเข้าถึง Deinitializers” - person Martin R; 24.02.2020