
RxSwift, Swift için geliştirilmiş reaktif programlama kütüphanesidir ve asenkron veri akışlarını yönetmeyi kolaylaştırır.
Reaktif Programlama Nedir? 🤔
Reaktif programlama, veri akışlarını yönetmeyi sağlayan bir programlama paradigmasıdır. Peki, bu ne demek?
Şöyle düşün: normalde, bir butona tıkladığında veya bir API isteği tamamlandığında, manuel olarak bir işlem başlatırsın, değil mi? İşte reaktif programlama burada devreye giriyor.
Reaktif programlama sayesinde, bu tür olayları veri akışları (observable streams) olarak tanımlıyoruz ve sistem bunları otomatik olarak izliyor. Yani, sen olayları sürekli kontrol etmek zorunda kalmadan, onlar gerçekleştiğinde otomatik olarak tepki verebiliyorsun. Bir nevi “benim yerime takip et ve haber ver” diyoruz.
RxSwift Nedir?
RxSwift, Swift için geliştirilmiş bir reaktif programlama kütüphanesi. Yani, yukarıda bahsettiğimiz veri akışlarını yönetmeyi kolay hale getiriyor.
Bunu bir haber ajansı gibi düşün:
- RxSwift sayesinde bir veri kaynağı oluşturuyorsun (mesela bir API’den hava durumu verisi çekiyorsun).
- Daha sonra bu veriyi dinleyenleri (observers) ekliyorsun (mesela kullanıcı arayüzü güncelleniyor).
- Yeni veri geldiğinde, sistem otomatik olarak haber veriyor ve güncelleniyor.
Özetle, RxSwift UI güncellemeleri, ağ istekleri ve kullanıcı etkileşimlerini yönetirken bizi gereksiz kod yazmaktan kurtaran bir kahraman!
Observable ve Observer Nedir?
- Observable (Gözlenen) → Bir veri kaynağıdır, yani veri üretir.
- Observer (Gözlemci) → Bu veriyi alıp işleyenler.
Bunu bir radyo istasyonu gibi düşünebilirsin; observable, radyo istasyonu ve sürekli müzik yayını yapıyor. Observer, radyoyu açıp müzik dinleyen insanlar.
Eğer radyoyu kapatırsan, müzik yayını devam eder ama sen artık dinleyemezsin. RxSwift’te de mantık aynı. Bir observable yayına devam eder ama onu dinleyen biri yoksa bir anlamı kalmaz.
Swift’te bir Observable nasıl oluşturulur?
import RxSwift
let observable = Observable.of("Merhaba", "RxSwift")
observable.subscribe { event in
print(event)
}
Observer, Observable’ın yaydığı verileri dinleyen kişidir . Observable bir değer ürettiğinde, Observer bunu yakalar ve belirli işlemleri gerçekleştirir.
Bunu garson — müşteri ilişkisi gibi düşünebilirsin:
• Observable = Bir garson, masalara yemek servisi yapıyor.
• Observer = Müşteri, garsondan gelen yemeği alıp afiyetle yiyor.
Garson yeni bir yemek getirdiğinde müşteri bunu alır ve yer (onNext).
Eğer garson yemeği düşürürse bir hata olur (onError).
Garson “bu son yemekti, mutfak kapandı” derse siparişler biter (onCompleted).
İşte Observer, Observable’dan şu olayları dinleyebilir:
- onNext → Yeni bir veri geldiğinde çalışır. (Yeni bir yemek geldi.)
- onError → Bir hata oluştuğunda çalışır. (Garson yemeği düşürdü, sipariş iptal!)
- onCompleted → Observable veri göndermeyi bitirdiğinde çalışır. (Restoran kapandı, sipariş bitti.)
Şimdi bunu kod ile nasıl yapacağımıza bakalım;
let observable = Observable.of("Swift", "RxSwift", "Observer")
let observer = observable.subscribe(
onNext: { value in
print("Gelen veri: \(value)")
},
onError: { error in
print("Hata oluştu: \(error)")
},
onCompleted: {
print("Observable tamamlandı.")
}
)
Çıktı:
Gelen veri: Swift
Gelen veri: RxSwift
Gelen veri: Observer
Observable tamamlandı.
Subjects Nedir?
Subjects, RxSwift’te hem Observable (veri üreten) hem de Observer (veriyi dinleyen) gibi davranabilen özel bir veri türüdür. Yani bir Subject, veri yayabilir ve bu verileri dinleyebilir.
Subjects Türleri :
RxSwift’te dört farklı Subject türü vardır. Bunları daha iyi anlamak için günlük hayattan örneklerle açıklayalım!
PublishSubject
Örneğin; canlı bir radyo yayını düşün. Yayını açtıktan sonra duyduklarını takip edebilirsin, ancak yayına geç katıldıysan, öncesinde ne söylendiğini bilemezsin!
Özellikleri :
- Veri yayabilir ve dinleyebilir.
- Yeni katılan dinleyiciler (aboneler), yalnızca katıldıktan sonraki verileri alır.
- Öncesinde yayılan verileri hatırlamaz.
import RxSwift
let subject = PublishSubject<String>()
subject.onNext("Yayın başladı!") // Bu mesajı kimse dinlemediği için kaybolur.
let subscriber1 = subject.subscribe(onNext: { value in
print("1. Dinleyici duydu: \(value)")
})
subject.onNext("Şimdi çalan şarkı: Emir Can İğrek") // 1. dinleyici duyacak.
let subscriber2 = subject.subscribe(onNext: { value in
print("2. Dinleyici duydu: \(value)")
})
subject.onNext("Yeni şarkı: Sagopa Kajmer") // Her iki dinleyici de duyacak.
Çıktı :
1. Dinleyici duydu: Şimdi çalan şarkı: Emir Can İğrek
1. Dinleyici duydu: Yeni şarkı: Sagopa Kajmer
2. Dinleyici duydu: Yeni şarkı: Sagopa Kajmer
BehaviorSubject
Örneğin; bir WhatsApp grubuna sonradan katıldığını düşün. Gruba girdiğinde, o an en son gönderilen mesajı görebiliyorsun, ama daha öncesini göremiyorsun. Ancak, bundan sonra atılan tüm mesajları da anlık olarak alıyorsun!
Özellikleri:
- Son yayılan veriyi hatırlar ve yeni katılanlara ilk olarak bu veriyi gönderir.
- Daha sonra gelen tüm yeni verileri de alırsın.
- Varsayılan (ilk) bir başlangıç değeri ile başlar.
import RxSwift
// Başlangıç değeri olan bir BehaviorSubject oluşturuyoruz.
let subject = BehaviorSubject(value: "Grup açıldı!")
// İlk abone, hemen en son değeri (başlangıç değerini) alır.
let subscriber1 = subject.subscribe(onNext: { value in
print(" 1. Kullanıcı gördü: \(value)")
})
// Yeni bir mesaj ekliyoruz.
subject.onNext("Merhaba, burası WhatsApp grubu!")
// İkinci kullanıcı gruba sonradan katılıyor.
let subscriber2 = subject.subscribe(onNext: { value in
print("2. Kullanıcı gördü: \(value)")
})
// Yeni bir mesaj daha ekliyoruz.
subject.onNext("Akşam yemeği planı yapalım mı?")
Çıktı :
1. Kullanıcı gördü: Grup açıldı!
1. Kullanıcı gördü: Merhaba, burası WhatsApp grubu!
2. Kullanıcı gördü: Merhaba, burası WhatsApp grubu!
1. Kullanıcı gördü: Akşam yemeği planı yapalım mı?
2. Kullanıcı gördü: Akşam yemeği planı yapalım mı?
ReplaySubject
Örneğin: bir YouTube oynatma listesi düşün. Listeye yeni bir kişi katıldığında, önceki videoların tamamını izleyebilir ve ardından yeni eklenen videoları da izlemeye devam edebilir!
Özellikleri:
- Kaç veri saklayacağını sen belirleyebilirsin. (bufferSize : 2 olarak belirledik.)
- Yeni katılanlar (aboneler) önce saklanan eski verileri alır, sonra gelen verileri de izlemeye devam eder.
- Tüm geçmişi saklayan bir Observable gibi davranır.
import RxSwift
// ReplaySubject oluşturuyoruz ve en fazla 2 eski değeri saklamasını sağlıyoruz.
let subject = ReplaySubject<String>.create(bufferSize: 2)
subject.onNext("Video 1: Giriş")
subject.onNext("Video 2: RxSwift Temelleri")
subject.onNext("Video 3: Subjects Nedir?")
// İlk kullanıcı katılıyor.
let subscriber1 = subject.subscribe(onNext: { value in
print(" 1. Kullanıcı izledi: \(value)")
})
// Yeni bir video ekleniyor.
subject.onNext("Video 4: Operatörler")
// İkinci kullanıcı gruba sonradan katılıyor.
let subscriber2 = subject.subscribe(onNext: { value in
print(" 2. Kullanıcı izledi: \(value)")
})
Çıktı :
1. Kullanıcı izledi: Video 2: RxSwift Temelleri
1. Kullanıcı izledi: Video 3: Subjects Nedir?
1. Kullanıcı izledi: Video 4: Operatörler
2. Kullanıcı izledi: Video 3: Subjects Nedir?
2. Kullanıcı izledi: Video 4: Operatörler
AsyncSubject
Örneğin: bir sınav sonuçlarını düşün. Öğrenciler sınava giriyor, kağıtlarını teslim ediyor, ama sonuçlar açıklanana kadar kimse bir şey öğrenemiyor. Sonuç açıklandığında herkes sadece en son sonucu görüyor.
Özellikleri:
- Sadece en son yayılan değeri saklar.
- Ancak, sadece tamamlandığında (onCompleted) bu değeri dinleyicilere iletir.
- Tamamlanmazsa (onCompleted çağrılmazsa), hiçbir veri gönderilmez.
import RxSwift
let subject = AsyncSubject<String>()
// İlk abonemiz konuya dahil oluyor ama şu an hiçbir veri alamaz.
let subscriber1 = subject.subscribe(onNext: { value in
print(" 1. Kullanıcı gördü: \(value)")
})
// Veri yayılıyor, ancak henüz kimseye iletilmiyor.
subject.onNext("Veri 1: 10")
subject.onNext("Veri 2: 20")
subject.onNext("Veri 3: 30") // Bu son veri, ancak hala kimse göremedi!
// Şimdi tamamlandığını belirtiyoruz.
subject.onCompleted()
// Yeni bir abone geliyor.
let subscriber2 = subject.subscribe(onNext: { value in
print("2. Kullanıcı gördü: \(value)")
})
Çıktı:
1. Kullanıcı gördü: Veri 3: 30
2. Kullanıcı gördü: Veri 3: 30
Hangi subject türü ne zaman kullanılır?

RxSwift ile UI Güncellemeleri
RxSwift, UI değişikliklerini yönetmek için harika bir araçtır. Normalde, delegate, NotificationCenter veya closure kullanarak UI’yi güncelleriz. Ancak, RxSwift sayesinde veri akışlarını doğrudan UI bileşenlerine bağlayabiliriz!
Şimdi, UIButton, UILabel, UITextField ve UITableView gibi bileşenleri RxSwift ile nasıl güncelleyebileceğimizi adım adım inceleyeceğiz.
Örnek: Buton tıklanınca UILabel güncelleme
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
let button = UIButton()
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
// Buton tıklamalarını dinleyerek Label'ı güncelle
button.rx.tap
.map { "Butona tıklandı! " }
.bind(to: label.rx.text)
.disposed(by: disposeBag)
}
}
Örnek: Kullanıcının yazdığı metni anlık olarak bir UILabel’e yansıtma
let textField = UITextField()
let label = UILabel()
textField.rx.text
.orEmpty // Optional'ı kaldır
.bind(to: label.rx.text) // Doğrudan bağla
.disposed(by: disposeBag)
Örnek: Basit bir UITableView Veri Bağlama
let tableView = UITableView()
let items = Observable.just(["Elma", "Muz", "Karpuz"])
items.bind(to: tableView.rx.items) { (tableView, row, item) in
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = item
return cell
}
.disposed(by: disposeBag)
DisposeBag ve Bellek Yönetimi
RxSwift kullanırken bellek yönetimi (Memory Management) çok kritik bir konudur. Eğer dikkat etmezsek, memory leak (bellek sızıntısı) oluşabilir ve uygulamamız gereksiz RAM tüketir. Bu da uygulamanın yavaşlamasına ve hatta çökmesine yol açabilir.
DisposeBag Nedir?
DisposeBag, RxSwift’te aboneliklerin (subscriptions) yönetilmesini sağlayan bir araçtır. İçine eklenen abonelikler, ViewController yok edildiğinde otomatik olarak iptal edilir (dispose edilir).
Peki neden önemli?
Normalde bir Observable’a abone olduğumuzda (subscribe), bu abonelik aktif kalmaya devam eder ve manuel olarak iptal etmezsek (dispose etmezsek), bellekte gereksiz yer kaplamaya devam eder. İşte DisposeBag, bunu otomatik olarak yönetir.
DisposeBag Kullanımı :
import UIKit
import RxSwift
class ViewController: UIViewController {
let disposeBag = DisposeBag() // DisposeBag oluştur
override func viewDidLoad() {
super.viewDidLoad()
let observable = Observable.of("Merhaba RxSwift!")
observable.subscribe(onNext: { value in
print(value) // "Merhaba RxSwift!" yazdır
})
.disposed(by: disposeBag) // DisposeBag içine ekledik!
}
}
Sonuç?
ViewController yok edildiğinde (deinit çağrıldığında), içindeki abonelikler de otomatik olarak sonlandırılacak ve bellek sızıntısı önlenecek!
Memory Leak (Bellek Sızıntısı) Nasıl Önlenir? 🔍
Bazı durumlarda DisposeBag kullanmak yetmez. Özellikle kendi içinde self kullanan closure’lar, ViewController’ı bellekten temizlenmesini engelleyebilir. Bu durumu çözmek için [weak self] veya [unowned self] kullanabiliriz.
Örnek: Memory Leak Oluşturan Kod
observable.subscribe(onNext: { value in
self.updateUI(value) // SELF burada döngüye sebep olabilir!
})
.disposed(by: disposeBag)
Sorun ne?
- Closure içindeki self doğrudan kullanıldığı için, ViewController kendini bellekten temizleyemez ve memory leak oluşur.
Çözüm: [weak self] Kullanımı
observable.subscribe(onNext: { [weak self] value in
self?.updateUI(value) // Self artık weak reference, memory leak oluşmaz!
})
.disposed(by: disposeBag)
Ne değişti?
- [weak self] sayesinde ViewController bellekten silindiğinde, closure da kendini otomatik olarak iptal eder.
- Memory leak önlendi!
Sonuç
RxSwift başta biraz kafa karıştırıcı gelebilir ama alışınca gerçekten kodu daha düzenli ve yönetilebilir hale getiriyor. UI ile entegrasyonu, veri akışlarını yönetmesi, asenkron işlemleri basitleştirmesi derken, bir süre sonra “Ben daha önce nasıl kod yazıyordum?” dedirtebilir.
Bir başka yazıda görüşene dek hoşçakalın! 🙋🏻♀️

