Swift dilinde otomatik bellek yönetimi (ARC) mekanizması nasıl çalışır?
sobes.tech yapay zeka
AI'dan gelen yanıt
ARC (Otomatik Referans Sayımı) otomatik olarak sınıf örneklerine referansları izler ve yönetir. Bir örneğe güçlü referans kalmadığında belleği serbest bırakır. ARC yalnızca sınıf örnekleriyle çalışır, yapılar veya enumlar ile değil, çünkü bunlar değer tipleridir.
İki örnek arasındaki üç bağlantı türü:
- Strong (Güçlü): Örneğin referans sayacını artıran bağlantı. Varsayılan olarak tüm referanslar güçlüdür.
- Weak (Zayıf): Referans sayacını artırmayan bağlantı. Güçlü referans döngülerini önlemek için kullanılır.
weaktüründeki referanslar her zaman opsiyoneldir, çünkü örnek herhangi bir zamanda serbest bırakılabilir. - Unowned (Mülksüz): Referans sayacını artırmayan ve bağlı örneğin daha uzun süre var olacağı garanti edilen durumlarda kullanılır. Zorunlu değildir, ancak serbest bırakılmış örneğe erişmeye çalışmak çalışma zamanı hatasıyla sonuçlanır.
Güçlü referans döngüleri, iki veya daha fazla sınıf örneğinin birbirine güçlü referanslar tuttuğu durumlarda ortaya çıkar ve ARC'nin serbest bırakmasını engeller. Bu döngüleri önlemek için weak veya unowned referanslar kullanılır.
Güçlü referans döngüsüne örnek:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit { // serbest bırakıldığında çağrılır
print("\(name) deinitialization oluyor")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
}
deinit { // serbest bırakıldığında çağrılır
print("Apartment \(unit) deinitialization oluyor")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil // Hiçbir şey yazdırılmaz, çünkü güçlü referans döngüsü var
Döngüyü weak ile çözme:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinitialization oluyor")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Zayıf referans
init(unit: String) {
self.unit = unit
}
deinit {
print("Apartment \(unit) deinitialization oluyor")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // Person serbest bırakılır
unit4A = nil // Apartment serbest bırakılır
unowned ile çözüm:
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinitialization oluyor")
}
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // Mülksüz referans
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Kart #\(number) deinitialization oluyor")
}
}
var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil // Customer ve CreditCard serbest bırakılır
ARC ve kapanışlar (closures): Closure'lar da güçlü döngüler oluşturabilir, sınıf örneklerini yakalayarak. Bunu önlemek için [weak self] veya [unowned self] kullanılır.
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { // lazy, self'yi kullanmadan önce kullanmak için
[unowned self] in // Yakalama listesi
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) deinitialization oluyor")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "merhaba, dünya")
print(paragraph!.asHTML())
paragraph = nil // HTMLElement serbest bırakılır