What is weak?

อะไรคือ weak

เราจะเห็นว่าเวลาเราผูก outlet หรือว่าทำ delegate เราจะประกาศตัวแปรโดยที่มี keyword weak ด้วย แลัว weak มันคืออะไร ไม่ใส่ได้ไหม

weak ย่อมาจาก weak references ซึ่งก็ตรงตัวตามชื่อคือใช้ได้กับ Type ที่เป็น reference type เท่านั้นนั่นก็คือพวก class แล้วทำไมต้อง reference แบบอ่อน ๆ

Automatic Reference Counting (ARC)

โดยปกติทุกครั้งที่เราสร้าง instance ของ class ขึ้นมา ARC จะต้องจองพื้นที่ใน memory ให้เราเพื่อใช้สำหรับเก็บ instance ที่เราสร้างขึ้น และเมื่อเราไม่ได้ใช้ instance นั้นแล้ว ARC ก็มีหน้าที่ที่จะต้องคืนพื้นที่ memory นั้นเพื่อให้สามารถนำกลับมาใช้งานอื่นได้อีก

เพื่อให้รู้ว่ายังต้องเก็บข้อมูลหรือคืนพื้นที่ memory ได้แล้ว ARC จึงต้องมีการนับว่ายังมี ตัวแปรหรือ property ไหนอีกไหมที่ยัง reference มายัง instance นี้อีก และ ARC จะไม่คืนพื้นที่ memory จนกว่า reference จะนับได้ศูนย์หรือก็คือไม่มีใครใช้งานแล้ว

เมื่อมีการสร้าง instance ใส่ลงตัวแปร หรือ property จะเป็นการสร้าง strong reference ให้ ARC นับ

Weak reference คืออะไร

เนื่องจาก ARC นับ reference เพื่อให้รู้ว่ายังต้องเก็บข้อมูลหรือคืนพื้นที่ memory และในบางครั้งเราก็อาจเขียนโค้ดที่ทำให้ไม่สามารถทำให้การนับ reference ลดลงเหลือศูนย์ได้ หรือก็คือเกิด cyclic เมื่อ instance แต่ละตัวต่าง reference ถึงกับแบบ strong reference ทำให้สามารถเกิดปัญหาการใช้งาน memory เพิ่มขึ้นเรื่อย ๆ และไม่สามารถคืนได้จนหมด เกิดเป็น memory leak แล้วทำให้แอปต้องหยุดการทำงานในที่สุด

ตัวอย่างเช่น เราสร้าง instance Person ไว้กับตัวแปร john และสร้าง instance Apartment ไว้กับ unit4A จากภาพจะเห็นว่าใน Person ก็มีการเก็บ Apartment และใน Apartment ก็มี Person และเมื่อเราไม่กำหนด weak ก็จะทำให้ทุก reference เป็น strong

เมื่อเราเลิก reference จากตัวแปร จะเห็นว่าเกิด cyclic ขึ้น และ ARC จะไม่สามารถคืน memory ได้ เพราะแต่ละ instance ยังคงนับได้ 1 เท่ากัน

weak reference จึงเกิดขึ้นเพื่อแก้ปัญหานี้ โดยที่ต้องมี reference เส้นใดเส้นหนึ่งเป็น weak เพื่อให้ ARC ไม่นับ

เมื่อเราเลิก reference จากตัวแปรทั้งคู่ จะเห็นว่า Person จะเหลือ strong reference ที่ชี้มาหาเป็นศูนย์ในขณะที่ Apartment ยังคงเหลือ 1 ทำให้ ARC คืนพื้นที่ในส่วน Person ก่อน

จากนั้นเมื่อได้คืน memoryในส่วนของ Person instance แล้ว strong reference ที่ชี้ไป Apartment instance ก็จะหายไปทำให้มี strong reference ลดลงเหลือศูนย์เช่นกัน ทำให้ ARC สามารถคืน memory จาก Apartment instance ได้

ดังนั้นเวลาเราใช้ delegate pattern เพื่อไม่ให้เกิด cyclic เราจึงใช้ weak ใน outlet ก็เช่นกัน เมื่อ view controller ไม่ได้เป็นคนสร้าง outlet นั้นเราจึงควรใส่ weak เพื่อเป็นการป้องกัน cyclic ที่อาจจะเกิดขึ้นได้

Last updated