Swinject adalah kontainer DI untuk Swift yang mengimplementasikan pola Dependency Injection dalam aplikasi iOS. Framework ini mengotomatiskan pembuatan dan injeksi dependensi, menghilangkan pengelolaan objek dan pabrik secara manual. Menurut data Swinject di GitHub, perpustakaan ini mendukung Constructor Injection, Property Injection, dan Method Injection dengan sistem scope yang fleksibel untuk mengelola siklus hidup.
Poin utama
Swinject adalah kontainer DI sumber terbuka untuk bahasa Swift, dirancang untuk menyederhanakan injeksi dependensi dalam aplikasi iOS, macOS, dan watchOS. Framework ini menggunakan pendekatan Service Locator: layanan didaftarkan dalam kontainer pusat, dan kontainer secara otomatis menyelesaikan grafik dependensi saat instance diminta.
Dependency Injection (DI) — pola desain di mana objek menerima dependensinya dari luar, bukan membuatnya di dalam. Ini mengurangi keterikatan antar komponen, menyederhanakan pengujian modular, dan memungkinkan penggantian implementasi tanpa mengubah kode konsumen.
Menurut Martin Fowler (2004), DI adalah kasus khusus dari Inversion of Control dan diimplementasikan melalui injeksi melalui konstruktor, properti, atau metode. Swinject mengotomatiskan proses ini, menghilangkan penulisan pabrik dan pencari layanan secara manual.
Terapkan Swinject dalam proyek dengan tiga atau lebih layanan yang memiliki dependensi silang, di mana konstruksi objek manual menyebabkan pertumbuhan kode inisialisasi dan penurunan testabilitas.
Swinject terintegrasi erat dengan ekosistem Apple dan mendukung semua versi Swift mulai dari 3.0. Framework ini kompatibel dengan Objective-C melalui jembatan, yang memungkinkan penerapannya dalam proyek yang ada yang ditulis dalam bahasa campuran tanpa migrasi kode penuh. Ini sangat relevan untuk aplikasi besar dengan riwayat pengembangan lebih dari lima tahun.
Kontainer Swinject diimplementasikan oleh kelas Container, yang menyimpan registri layanan terdaftar. Saat metode resolve dipanggil, kontainer membuat objek, menyelesaikan semua dependensinya secara rekursif sesuai grafik registrasi.
Container — objek pusat di mana korespondensi antara abstraksi dan implementasinya didaftarkan. Service adalah protokol yang mendefinisikan kontrak, dan Component adalah kelas yang mengimplementasikan protokol ini. Pendaftaran dilakukan melalui metode register, yang menerima tipe layanan dan pabrik.
let container = Container()
container.register(Networking.self) { _ in
NetworkService()
}
let service = container.resolve(Networking.self)
Metode resolve mengembalikan instance dari implementasi konkret yang terdaftar untuk protokol yang ditentukan. Jika dependensi tidak terdaftar, kontainer melempar kesalahan fatal untuk deteksi cepat masalah pada tahap pengembangan.
Setiap pendaftaran membuat entri dengan fungsi pabrik dan scope yang dipilih. Satu layanan dapat memiliki beberapa pendaftaran dengan nama berbeda, yang memungkinkan pemilihan implementasi konkret berdasarkan nama — berguna untuk lingkungan yang berbeda (pengembangan, staging, produksi).
Proses penyelesaian dependensi (resolution) bekerja secara rekursif: ketika kontainer membuat instance Component, ia menganalisis penginisialisasinya dan untuk setiap parameter memanggil resolve dari tipe yang sesuai. Jika dependensi juga memiliki dependensinya sendiri, proses berlanjut hingga seluruh grafik selesai dibangun. Kedalaman penyarangan hanya dibatasi oleh memori yang tersedia, namun dalam praktiknya jarang melebihi lima tingkat.
Swinject mendukung tiga cara utama injeksi dependensi, masing-masing dapat diterapkan tergantung pada konteks arsitektur.
Constructor Injection — injeksi dependensi melalui parameter penginisialisasi. Ini adalah cara yang lebih disukai, yang menjamin bahwa objek selalu dalam keadaan yang benar sejak saat pembuatan. Swinject secara otomatis menyelesaikan semua dependensi yang diteruskan ke konstruktor.
class LoginViewModel {
private let authService: AuthProtocol
init(authService: AuthProtocol) {
self.authService = authService
}
}
container.register(AuthProtocol.self) { _ in
AuthService()
}
container.register(LoginViewModel.self) { r in
LoginViewModel(authService: r.resolve(AuthProtocol.self)!)
}
Property Injection — injeksi melalui pengaturan properti objek setelah inisialisasinya. Digunakan ketika dependensi bersifat opsional atau tidak dapat diteruskan melalui konstruktor, misalnya saat bekerja dengan Storyboard, di mana view controller dibuat secara otomatis. Swinject mendukung anotasi @Inject untuk injeksi properti otomatis melalui runtime tanpa panggilan resolve eksplisit.
Saat menggunakan Property Injection, penting untuk memastikan bahwa dependensi telah diatur sebelum akses pertama ke objek. Jika tidak, properti akan tetap nil, yang menyebabkan crash tak terduga. Swinject memecahkan masalah ini melalui mekanisme Implicitly Unwrapped Optional dan verifikasi ketat pada tahap penyelesaian grafik dependensi.
Method Injection — injeksi melalui parameter metode. Diterapkan untuk layanan yang hanya diperlukan untuk menjalankan satu operasi dan tidak boleh disimpan sebagai status permanen objek. Ini adalah metode injeksi yang paling jarang digunakan, namun berguna untuk callback.
ObjectScope — mekanisme yang menentukan siklus hidup instance yang dibuat di dalam kontainer Swinject. Framework menyediakan tiga scope bawaan dengan kemampuan untuk membuat scope kustom melalui protokol ObjectScopeProtocol.
Scope graph — nilai default. Setiap panggilan resolve membuat instance baru yang hanya hidup selama penyelesaian grafik dependensi. Ini adalah pilihan aman untuk layanan tanpa status karena menghilangkan kebocoran memori akibat caching.
Scope container — singleton dalam kontainer. Instance dibuat satu kali saat resolve pertama dan dikembalikan pada semua permintaan berikutnya. Cocok untuk layanan dengan status bersama: cache data, logger, pengaturan aplikasi.
Scope transient — setiap panggilan resolve membuat instance baru tanpa caching. Digunakan untuk objek ringan yang tidak perlu digunakan kembali — misalnya, untuk modul yang bekerja dengan permintaan HTTP tertentu.
| Scope | Siklus hidup | Penggunaan yang disarankan |
|---|---|---|
| graph | Selama penyelesaian grafik | Layanan tanpa status secara default |
| container | Seluruh siklus hidup kontainer | Singleton: cache, logger, klien jaringan |
| transient | Tanpa caching | Objek ringan untuk penggunaan sekali pakai |
Integrasi Swinject dalam proyek iOS nyata dimulai dengan inisialisasi kontainer saat aplikasi dimulai — di AppDelegate atau scene. Disarankan untuk menstrukturkan pendaftaran melalui Assembly: kelas atau struktur terpisah yang mengelompokkan layanan terkait.
Menurut survei Swift Developer Community (2025), 43% pengembang iOS menggunakan kontainer DI dalam proyek komersial untuk mengelola dependensi lapisan jaringan, repositori, dan koordinator navigasi. Swinject tetap menjadi solusi paling populer berkat sintaks minimal dan kompatibilitas dengan Objective-C.
Storyboard Injection — kemampuan unik Swinject: kontainer secara otomatis menginjeksi dependensi ke view controller yang dibuat dari Storyboard, tanpa kode tambahan di AppDelegate. Untuk ini, resolver khusus digunakan yang diteruskan ke UIStoryboard melalui metode init(container:), yang mencegat pembuatan view controller dan menginjeksi dependensi terdaftar.
Dalam proyek besar, Swinject dapat dikombinasikan dengan koordinator navigasi: koordinator menerima kontainer dan membuat layar, menyelesaikan dependensi mereka melalui resolve, mempertahankan titik konfigurasi tunggal untuk seluruh scene.
Arsitektur dengan Assembly — pola yang disarankan untuk mengatur pendaftaran. Setiap Assembly mengelompokkan layanan terkait (misalnya, NetworkingAssembly, DatabaseAssembly) dan dapat bergantung pada Assembly lain. Saat inisialisasi kontainer, semua Assembly dimuat dan mendaftarkan layanan mereka, memberikan pemisahan tanggung jawab yang jelas dan menyederhanakan navigasi melalui konfigurasi DI dalam proyek besar dengan puluhan layanan.
Untuk debugging grafik DI, Swinject menyediakan ekstensi SwinjectPropertyLoader, yang memuat konfigurasi dari file plist, dan SwinjectStoryboard — integrasi dengan storyboard melalui versi khusus UIStoryboard. Alat-alat ini sangat berguna pada tahap mentransisikan proyek yang ada dari konstruksi objek manual ke DI: pengembang dapat secara bertahap mendaftarkan layanan, memeriksa grafik dependensi melalui pengujian dan pencatatan kesalahan resolusi, tanpa menghentikan pengembangan fitur utama aplikasi.
Swinject juga menyediakan integrasi dengan RxSwift dan Combine melalui ekstensi SwinjectAutoregistration untuk penyelesaian dependensi otomatis berdasarkan tipe parameter penginisialisasi tanpa pendaftaran pabrik secara eksplisit. Ini mengurangi jumlah kode pendaftaran untuk layanan sederhana: cukup panggil container.register(ServiceProtocol.self) tanpa menentukan pabrik, dan Swinject akan secara mandiri membangun pabrik berdasarkan refleksi Signal yang disediakan oleh runtime Swift. Pendekatan ini direkomendasikan untuk layanan yang konstruktornya hanya menerima tipe dasar dan tidak memerlukan logika kompleks saat pembuatan.
Pertanyaan yang sering diajukan
Swinject ditulis dalam Swift murni tanpa generasi kode dan refleksi. Tidak seperti Needle, ia tidak memerlukan generasi kode sumber, dan dibandingkan dengan Dip — ia menyediakan dukungan bawaan untuk Storyboard Injection, yang menyederhanakan integrasi ke dalam proyek UIKit yang ada.
Tambahkan paket melalui URL github.com/Swinject/Swinject melalui Xcode di menu File — Add Packages. Instalasi melalui CocoaPods dan Carthage juga tersedia. Setelah instalasi, impor modul Swinject dan buat instance Container.
Ya, Swinject sepenuhnya kompatibel dengan SwiftUI. Dependensi diinjeksi melalui penginisialisasi View atau melalui Environment, di mana kontainer diteruskan sebagai EnvironmentObject. Swinject tidak bergantung pada UIKit dan bekerja sama dengan kedua framework.
Buat kontainer terpisah untuk pengujian, ganti layanan nyata dengan mock. Swinject memungkinkan penimpaan pendaftaran tanpa mengubah kode konsumen. Setiap pengujian mendapatkan kontainer terisolasi dengan serangkaian dependensi minimal.
Untuk analitik gunakan scope container, sehingga semua layar mengirim peristiwa melalui satu instance. Ini menjamin antrian pengiriman yang seragam dan agregasi batch yang benar tanpa duplikasi data antar konsumen yang berbeda.
Ringkasan
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