Combine adalah framework pemrograman reaktif dari Apple, diperkenalkan di iOS 13. Menurut Apple Documentation, 2025, Combine menyediakan API deklaratif terpadu untuk memproses peristiwa asinkron. Publisher menentukan sumber data, dan Subscriber berlangganan untuk menerimanya.
Utama
Combine adalah framework Swift deklaratif untuk memproses peristiwa asinkron dari waktu ke waktu. Tidak seperti pendekatan berbasis callback, Combine memungkinkan deskripsi pipeline pemrosesan data melalui rantai operator. Framework ini terintegrasi dengan Foundation (URLSession, Timer, NotificationCenter) dan SwiftUI (ObservableObject, @Published).
Setiap tipe yang mengimplementasikan protokol Publisher harus menentukan Output (tipe nilai) dan Failure (tipe kesalahan). Publisher tidak aktif hingga berlangganan — mulai memancarkan peristiwa hanya setelah subscribe dipanggil. Ini adalah semantik dingin, karakteristik aliran reaktif, yang meningkatkan efisiensi.
Subscriber menerima peristiwa melalui tiga metode: receive(subscription:) — konfirmasi langganan dengan manajemen demand; receive(_:) — menerima nilai baru; receive(completion:) — penyelesaian aliran dengan sukses atau kesalahan. Demand menentukan jumlah nilai yang siap diterima Subscriber — ini adalah mekanisme backpressure.
Apple menyediakan banyak Publisher bawaan: Just memancarkan satu nilai dan selesai, Future — hasil asinkron dengan closure, Deferred — pembuatan Publisher yang ditangguhkan hingga saat berlangganan. URLSession.dataTaskPublisher mengubah permintaan jaringan menjadi aliran reaktif. Timer.publish membuat timer periodik. NotificationCenter.default.publisher mengubah notifikasi menjadi Publisher. Integrasi ini memungkinkan berlangganan peristiwa tanpa jembatan manual.
Di Combine, Publisher dan Subscriber terhubung melalui protokol Subscription. Subscription adalah objek penghubung yang mengontrol aliran data. Pengembang tidak perlu membuat tipe Publisher sendiri — Apple menyediakan Publisher bawaan: Just, Future, Deferred, Fail, Empty, serta Publisher untuk URLSession dan Timer.
Subject adalah Publisher yang dapat menerima nilai secara manual. PassthroughSubject tidak menyimpan status: pelanggan hanya menerima peristiwa yang terjadi setelah berlangganan. CurrentValueSubject, mirip dengan BehaviorRelay di RxSwift, menyimpan nilai saat ini dan segera meneruskannya ke pelanggan baru.
Mekanisme backpressure di Combine mengatur kecepatan transmisi data. Subscriber memberi tahu Publisher melalui subscription.request(.unlimited) atau subscription.request(.max(N)) berapa banyak nilai yang siap diproses. Ini mencegah luapan buffer pada kecepatan yang tidak merata antara produsen dan konsumen.
Combine mencakup lebih dari 100 operator yang dibagi ke dalam kategori: transformasi (map, tryMap, flatMap), penyaringan (filter, compactMap, removeDuplicates), penggabungan (combineLatest, merge, zip), manajemen waktu (debounce, throttle, delay) dan penanganan kesalahan (catch, replaceError, retry).
Operator combineLatest menggabungkan nilai terakhir dari dua Publisher — setiap kali salah satu dari mereka memancarkan nilai baru, closure dipanggil dengan kedua nilai yang diperbarui. Operator ini sangat diperlukan dalam validasi formulir di mana status beberapa bidang input perlu dilacak secara bersamaan.
Operator debounce menunda publikasi nilai hingga interval yang ditentukan berlalu tanpa peristiwa baru. Ini sangat penting untuk bidang pencarian: permintaan ke server dikirim hanya setelah pengguna berhenti mengetik selama 300-500 md, mengurangi beban 5-10 kali lipat.
Combine menawarkan beberapa strategi penanganan kesalahan di tingkat operator. catch menangkap Failure dan mengganti Publisher dengan cadangan — aliran berlanjut tanpa crash. replaceError(with:) menempatkan nilai default sebagai pengganti kesalahan. retry(_:) mengulangi langganan sejumlah kali tertentu saat gagal. Penting: tipe kesalahan Never di tanda tangan Publisher menjamin bahwa aliran tidak akan pernah berakhir dengan kesalahan — ini memungkinkan penggunaan Publisher di SwiftUI tanpa penanganan Failure.
Contoh pertama menunjukkan kerja dasar dengan Just — Publisher yang memancarkan satu nilai dan selesai:
let publisher = Just("Hello Combine")
publisher
.sink(receiveCompletion: { completion in
print("Selesai: \(completion)")
}, receiveValue: { value in
print("Diterima: \(value)")
})
Contoh kedua mendemonstrasikan integrasi Combine dengan URLSession untuk permintaan jaringan dengan pemrosesan hasil di thread utama:
let url = URL(string: "https://api.example.com")!
URLSession.shared
.dataTaskPublisher(for: url)
.map { $0.data }
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
if case .failure(let error) = completion {
print("Kesalahan: \(error)")
}
}, receiveValue: { data in
print("Data diterima: \(data.count)")
})
Contoh ketiga — penggunaan CurrentValueSubject untuk manajemen status:
let counter = CurrentValueSubject<Int, Never>(0)
counter
.sink { value in
print("Penghitung: \(value)")
}
counter.send(1) // Menampilkan: Penghitung: 1
counter.send(2) // Menampilkan: Penghitung: 2
print(counter.value) // Menampilkan: 2
Combine dan RxSwift memecahkan tugas yang sama — pemrograman reaktif, tetapi dengan pendekatan yang berbeda. Combine adalah framework native Apple yang terpasang di sistem: tidak memerlukan instalasi dependensi, terintegrasi dengan SwiftUI dan Foundation. RxSwift adalah pustaka pihak ketiga dengan dukungan iOS 9+ dan kumpulan operator yang lebih luas.
Kinerja Combine lebih tinggi dalam skenario tipikal berkat implementasi native di C. RxSwift menyediakan lebih banyak alat debugging (RxSwift.Resources.total, Debug), tetapi arsitektur berorientasi objeknya mungkin kurang efisien pada aliran data besar. Pilihan di antara keduanya adalah kompromi antara kemampuan dan integrasi.
Perbedaan penting — model backpressure. Di Combine, Subscriber mengelola demand melalui Subscription, yang memberikan kontrol eksplisit atas kecepatan aliran. Di RxSwift, backpressure tidak dikontrol secara default — Observable memancarkan semua nilai dan Subscriber memprosesnya saat tiba. Untuk aliran data besar, Combine terbukti lebih dapat diprediksi dan lebih aman dari segi memori.
Combine terintegrasi secara mendalam dengan SwiftUI di tingkat bahasa. @Published menghasilkan Publisher, ObservableObject menyediakan objectWillChange Publisher. SwiftUI View secara otomatis berlangganan Publisher ini dan menggambar ulang saat perubahan. Untuk UIKit ada pembungkus pihak ketiga seperti CombineCocoa, tetapi Combine pada awalnya dirancang untuk SwiftUI, sehingga integrasinya di UIKit memerlukan kode tambahan. RxSwift, sebaliknya, memiliki ekosistem yang kaya untuk UIKit: RxCocoa menyediakan pembungkus reaktif untuk semua elemen UI.
Combine mendukung integrasi dengan Core Data melalui NSFetchedResultsController Publisher. Publisher memancarkan data baru pada setiap perubahan tumpukan Core Data: penambahan, penghapusan, pembaruan catatan. Ini memungkinkan pembangunan daftar reaktif tanpa memanggil reloadData secara manual. Dengan menggabungkan Combine dengan NotificationCenter Publisher untuk UIApplication.willResignActiveNotification, pengembang menciptakan lapisan reaktif untuk seluruh siklus hidup aplikasi tanpa delegasi dan callback. Untuk kelas ObservableObject, SwiftUI secara otomatis memperbarui View saat properti @Published berubah — Combine menyediakan seluruh koneksi tanpa satu baris kode manual. Pengujian modular kode Combine dilakukan melalui XCTestExpectation dan Publisher.sink dalam kasus uji dengan isolasi Scheduler melalui ImmediateScheduler.
Saat bekerja dengan Combine di proyek UIKit, pengembang sering menggunakan langganan melalui sink dan menyimpan AnyCancellable di Set. Pola tipikal: ViewController membuat tampilan, menyimpan cancellables, berlangganan ke Publisher dari ViewModel. Saat deinit, semua langganan secara otomatis dibatalkan melalui koleksi Cancellables. Untuk bekerja dengan benar dengan UIControl di Combine, UIControl.Event Publisher dapat digunakan melalui ekstensi publisher(for:).
Debugging Combine dilakukan melalui operator print() atau handleEvents(). print(String) mencatat semua peristiwa: receive subscription, request demand, receive value, receive completion. handleEvents memberikan kontrol yang lebih halus: closure dapat ditentukan untuk setiap tahap siklus hidup Publisher. Untuk pengujian Combine ada CombineExpectations — pustaka yang memungkinkan pemeriksaan bahwa Publisher memancarkan nilai yang diharapkan dalam pengujian dengan waktu virtual dan kontrol demand.
Combine secara aktif digunakan di SwiftUI untuk manajemen formulir: setiap properti @Published menghasilkan Publisher, SwiftUI berlangganan melaluinya View.body. Dengan menggabungkan beberapa Publisher melalui combineLatest, validasi formulir menjadi deklaratif: setiap Publisher melacak satu bidang, combineLatest mengumpulkan semua nilai, map memeriksanya dan mengembalikan status tombol Submit. Publishers.Merge menggabungkan beberapa Publisher dari tipe yang sama menjadi satu — berguna untuk mengumpulkan peristiwa dari berbagai kontrol ke dalam satu aliran.
Untuk integrasi Combine dengan UIKit gunakan UIControl Publisher melalui ekstensi: button.publisher(for: .touchUpInside) mengembalikan Publisher yang memancarkan peristiwa saat ditekan. CombineCocoa — pustaka komunitas yang menyediakan Publisher untuk semua peristiwa UIControl, UITextView.text, UIScrollView.contentOffset. Saat pembatalan langganan, cancellables Store dibersihkan di deinit, menjamin bahwa tidak ada langganan yang bertahan lebih lama dari pemiliknya. Untuk UIControl dengan banyak status, gunakan Publishers.MergeMany untuk menggabungkan Publisher dalam array.
Pertanyaan yang Sering Diajukan
Combine tersedia sejak iOS 13, macOS 10.15, tvOS 13 dan watchOS 6. Ini membatasi penggunaannya dalam proyek yang memerlukan dukungan untuk versi yang lebih lama. Untuk iOS 12 dan sebelumnya, RxSwift atau pustaka pihak ketiga digunakan.
PassthroughSubject tidak menyimpan status dan tidak mengulangi nilai terakhir kepada pelanggan baru — mereka hanya menerima peristiwa di masa depan. CurrentValueSubject menyimpan nilai saat ini dan segera meneruskannya ke pelanggan baru. CurrentValueSubject.value memungkinkan membaca dan menulis nilai saat ini secara sinkron.
Combine menjadi dasar SwiftUI: @Published menghasilkan Publisher, ObservableObject menggunakan objectWillChange Publisher. SwiftUI View secara otomatis berlangganan ke @ObservedObject dan @StateObject melalui pipeline Combine, menggambar ulang View saat properti berubah.
Backpressure — mekanisme manajemen kecepatan transmisi data. Subscriber memberi tahu Subscription berapa banyak nilai yang siap diproses (demand). Publisher tidak dapat memancarkan lebih dari yang diminta. Ini sangat penting saat bekerja dengan aliran data besar dari soket jaringan.
Operator catch menangkap kesalahan dan mengganti Publisher dengan fallback. replaceError mengganti kesalahan dengan nilai default. retry mengulangi langganan sejumlah kali tertentu saat terjadi kesalahan. Semua operator harus ditempatkan sebelum subscribe untuk menghindari crash saat Failure.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga