Swift’te Bellek Yönetimi: Pratik Örneklerle İncelikler

Zafer Çalışkan
Appcent
Published in
2 min readJun 28, 2024

Uygulama geliştirme sürecinde karşılaşılan en zorlu sorunlardan biri, memory leak’lerdir. Kişisel projelerimde de deneyimlediğim gibi, özellikle reaktif programlama kütüphaneleri kullanırken abonelik(subscription) yönetimi ve güçlü referansların kontrolsüz kullanımı, beklenmeyen bellek sızıntılarına(leaks) neden olabilir. Örneğin, RxSwift aboneliklerini DisposeBagkullanmadan yönetmek, aboneliklerin zamanında serbest bırakılmamasına ve uygulamanın performansının düşmesine sebep olabilir.

Başka bir örnek ise, delegate’lerin güçlü referanslarla(strong reference) tutulması sonucunda oluşan döngüsel referanslardır(retain cycle). Bu durum, nesnelerin beklenmeyen şekilde bellekte kalmasına ve uygulamanın kaynaklarını gereksiz yere tüketmesine yol açabilir. Bu tür hataların önlenmesi için, doğru programlama pratiklerini uygulamak ve uygun araçları kullanmak önemlidir.

Bu makalede, kendi projelerimden edindiğim deneyimleri ve bu tür bellek yönetimi hatalarını nasıl önleyebileceğimizden bahsedeceğim. Bu sayede, benzer sorunlarla karşılaşan diğer geliştiricilere yardımcı olmayı ve memory leaks konusunda daha kararlı uygulamaların geliştirilmesine katkıda bulunmayı amaçlıyorum.

Örnek #1

Açıklama:

Bu örnekteki ilk memory leak sebebi FavoritesHelper sınıfının içindeki “self” referansının retain cycle’a neden olmasıdır. Bu retain cycle’ı kırmak için “weak” veya “unowned” self kullanabiliriz. Bu sayede FavoritesHelper nesnesinin “subscribe” içinde güçlü bir referansla tutulmasını engellemiş oluruz.

İkinci memory leak sebebi ise “DisposeBag” kullanılmadığı için oluşmaktadır. RxSwift ile çalışırken, aboneliklerin (subscriptions) yönetilmesi ve doğru bir şekilde serbest bırakılması önemlidir.“DisposeBag”, abonelikleri yönetmek ve belirli bir yaşam döngüsü boyunca aboneliklerin serbest bırakılmasını sağlamak için kullanılır. Eğer “DisposeBag” kullanılmazsa, abonelikler serbest bırakılmaz ve memory leak oluşur.

Sonuç:

Örnek #2

Açıklama:

Bu örnekte birden fazla sayıda memory leak oluşturacak “strong reference” property bulunuyor. Bu property’ler retain cycle oluşturmaktadır.

  1. Strong Reference: SimpleJokeCell içerisinde bulunan “viewModel” referansını “strong reference” olarak tutulması memory leak’e sebep olmaktadır. Bu leak’i engellemek için “viewModel” referansını “weak reference” olarak kullanabiliriz.
  2. Closure Retain Cycle: SimpleJokeCell içerisinde bulunan “cellForRowAt” closure’ı, “self” referansını “strong” olarak tutar. Bu, closure’ın SimpleJokeCell nesnesini serbest bırakmasını engeller ve retain cycle oluşturur. Bu leak’i closure içerinde “self”i “weak reference” olarak kullanarak engelleyebiliriz.
  3. Delegate Retain Cycle: SimpleJokeCell’in, SimpleJokeTableViewCell’in “delegate” i olarak atanması retain cycle oluşturabilir. SimpleJokeTableViewCell'in “delegate” i güçlü bir referans olarak tutuluyorsa ve SimpleJokeCell de SimpleJokeTableViewCell'i güçlü bir referansla tutuyorsa, retain cycle oluşur. Bu leak'i SimpleJokeTableViewCell’in “delegate” property’sini “weak reference” yaparak engelleyebiliriz.

Sonuç:

Örnek #3

Açıklama:

NotificationCenter” observer'ları “strong reference” tutar. İhtiyacımız bittiğinde observer'ları kaldırmazsak, “strong reference” oluşur ve EditMessageViewController serbest bırakılamaz. Bu leak’i engellemek için “viewDidDisappear” içerisinde observer’ları kaldırabiliriz.

Sonuç:

Bu makalede paylaştığım deneyimlerimin, sizin projelerinizde de faydalı olacağını umuyorum. Yazılım geliştirme sürecinde hatalardan öğrenmek ve bu hataları gelecekteki projelerimizde önlemek, her zaman önemli bir adımdır. Doğru pratikleri benimsemek ve kodunuzu düzenli olarak gözden geçirmek, hem uygulamanızın kalitesini artırır hem de geliştirici olarak sizin kendinizi geliştirmenize yardımcı olur.

Bana Linkedin veya X üzerinden ulaşabilirsiniz.

--

--