- Published on
Swiftda Strong va Weak Referencelar
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Swiftda ARC (Automatic Reference Counting) xotirani avtomatik ravishda ajratish va bo'shatishni boshqaradi.
Ammo reference turini belgilash orqali ARC ning xotirani avtomatik bo'shatishini oldini olishimiz mumkin. Masalan, strong reference instancelarni qattiq ushlab turadi va ARC tomonidan bo'shatilishiga yo'l qo'ymaydi.
Xuddi shunday, weak reference instancelarni ARC tomonidan bo'shatilishdan himoya qila olmaydi.
Strong va weak reference haqida o'rganishdan oldin Swiftda classlar va obyektlar qanday ishlashini tushunib olish kerak.
Property e'loni standart bo'yicha strong hisoblanadi. Weak referenceni e'lon qilish uchun
weakkalit so'zidan foydalanamiz.
Strong Reference
Swiftda class instancesini yaratganimizda, reference count qiymati 0 dan 1 ga oshiriladi. Xuddi shunday, agar instanceni bo'shatsak, count 0 ga kamayadi. Keling, misolni ko'raylik:
class Employee {
var name: String // ism
var colleague: Employee? // hamkasb
// initializer e'lon qilish
init(name: String) {
self.name = name
}
}
// Employee dan ikkita obyekt yaratish
var sabby: Employee? = Employee(name: "Sabby")
var cathy: Employee? = Employee(name: "Cathy")
Yuqoridagi misolda Employee classining sabby va cathy instancelarini yaratdik. Endi sabby va cathy instancelarining reference counti 1 ga teng.
Bu yerda class ichida strong reference yaratdik:
var colleague: Employee?
Endi ushbu referenceni sabby ning colleague propertysi cathy ga murojaat qilishi uchun ishlatamiz:
sabby?.colleague = cathy
Bu holda cathy uchun yangi reference yaratiladi, bu cathy ning reference countini 1 dan 2 ga oshiradi.
Xuddi shunday, agar sabby ni cathy ning colleague iga tayinlasak, sabby ning reference counti 2 ga oshadi:
cathy?.colleague = sabby
Bu yerda sabby va cathy instancelarining ikkalasi ham reference count 2 ga ega bo'ladi.
Instancelarni bo'shatish
Swiftda xotira instancesi faqat uning reference counti 0 bo'lsa bo'shatiladi. Va xotira instancelarini qo'lda bo'shatish uchun referencega nil tayinlaymiz. Masalan,
sabby = nil
cathy = nil
Instancega nil tayinlaganimizda, instancelarning reference counti 1 ga kamayadi. Bu yerda yuqoridagi kod sabby va cathy ning reference countini 1 ga kamaytiradi.
Ammo strong referencelar tufayli sabby va cathy ning reference counti 2 ga teng, shuning uchun bo'shatishdan keyingi yakuniy reference count 1 bo'ladi (2 - 1).
Shuning uchun strong referenceslar sabby va cathy bo'shatilmaydi (reference count 0 ga teng emas).
Class turi optional turda bo'lishi kerak, shunda o'sha classning obyektlariga
niltayinlashimiz mumkin. Shuning uchun bizEmployeeo'rnigaEmployee?dan foydalandik.
Misol:
// class e'lon qilish
class Employee {
var name: String // ism
var salary: Int // maosh
var colleague: Employee? // hamkasb
// initializer e'lon qilish
init(name: String, salary: Int) {
self.name = name
self.salary = salary
}
// deinitializer e'lon qilish
deinit {
print("Xotira bo'shatildi")
}
}
// Employee instancelarini yaratish
var sabby: Employee? = Employee(name: "Sabby", salary: 50000)
var cathy: Employee? = Employee(name: "Cathy", salary: 45000)
// cathy va sabby ning reference countini 2 ga oshirish
sabby?.colleague = cathy
cathy?.colleague = sabby
// obyektlarni bo'shatish
sabby = nil
cathy = nil
Yuqoridagi misolda sabby va cathy instancelariga nil tayinladik. Ammo sabby va cathy strong referencelar bo'lib, ularni bo'shatish faqat ularning reference countini 2 dan 1 ga kamaytiradi.
Shuning uchun deinitializer
deinit {
print("Xotira bo'shatildi")
}
chaqirilmaydi va hech qanday natija olmaymiz.
Agar instancelarni to'liq bo'shatishni xohlasak, o'rniga weak referencelardan foydalanamiz.
Weak Reference
Avvalroq aytib o'tganimizdek, weak reference obyektni bo'shatilishdan himoya qilmaydi. Buning sababi, propertyni weak deb e'lon qilganimizda, o'sha propertyning reference counti hech qachon 1 dan ortiq bo'lmaydi.
class Employee {
weak var colleague: Employee?
...
}
Bu yerda colleague ni weak property sifatida belgilash uchun weak kalit so'zidan foydalandik.
Agar property e'lon qilishda hech narsa yozmasak, u avtomatik ravishda strong hisoblanadi. Weak qilish uchun esa oldidan
weakkalit so'zini yozishimiz kerak.
Misol:
// class e'lon qilish
class Employee {
var name: String // ism
var salary: Int // maosh
// weak property e'loni
weak var colleague: Employee? // hamkasb
// initializer e'lon qilish
init(name: String, salary: Int) {
self.name = name
self.salary = salary
}
// deinitializer e'lon qilish
deinit {
print("Xotira bo'shatildi")
}
}
// Employee instancelarini yaratish
var sabby: Employee? = Employee(name: "Sabby", salary: 50000)
var cathy: Employee? = Employee(name: "Cathy", salary: 45000)
// sabby instancening colleague propertysi cathy instancega murojaat qiladi
sabby?.colleague = cathy
// cathy instancening colleague propertysi sabby instancega murojaat qiladi
cathy?.colleague = sabby
// obyektlarni bo'shatish
sabby = nil
cathy = nil
Natija:
Xotira bo'shatildi
Xotira bo'shatildi
Yuqoridagi misolda Employee classining sabby va cathy instancelarini yaratdik.
var sabby: Employee? = Employee(name: "Sabby", salary: 50000)
var cathy: Employee? = Employee(name: "Cathy", salary: 45000)
Endi sabby va cathy ning reference counti 1 ga teng.
Bu yerda sabby ning colleague propertysi cathy ga va aksincha murojaat qildik:
sabby?.colleague = cathy
cathy?.colleague = sabby
Bu holda sabby va cathy ning reference counti 1 ligicha qoladi, chunki bu safar colleague propertysi uchun weak referenceni ishlatdik.
Shuning uchun instancelarni bo'shatganimizda:
sabby = nil
cathy = nil
Referencelar to'liq bo'shatiladi va deinitializer chaqiriladi:
deinit {
print("Xotira bo'shatildi")
}
Shuning uchun Xotira bo'shatildi natijasini olamiz.
Xulosa
- Strong Reference β obyektlarni xotiradan bo'shatilishdan himoya qiladi (standart)
- Weak Reference β obyektlarni xotiradan bo'shatilishdan himoya qilmaydi
- Weak reference memory leak (xotira oqishi) muammosini oldini oladi
- Weak propertylar doimo optional turda bo'lishi kerak