Dependency Injection, yazılım geliştirme süreçlerinde bağımlılıkları daha iyi yönetmek, test edilebilir ve esnek bir kod oluşturmak için kullanılan bir tekniktir. SwiftUI’da Dependency Injection kullanımını açıklamak için gerçek hayat senaryolarından bir örnek verelim.
Örneğin, bir uygulama geliştiriyorsanız ve HTTP istekleri yapmanız gerekiyorsa, URLSession sınıfını veya Alamofire kütüphanesini kullanmanız gerekebilir. Dependency Injection kullanarak, bu bağımlılıkları uygulamanın diğer bileşenlerine enjekte edebilirsiniz. Bu, bu bağımlılıkların uygulama içinde daha kolay değiştirilebilir ve test edilebilir hale gelmesini sağlar.
Önce, bir URLSession
kullanarak bir NetworkManager oluşturacağız. Daha sonra, bu NetworkManager’ı ViewModel’de veya başka bir yerde kullanabiliriz. Ardından, aynı şeyi Alamofire ile yapacağız.
// Dependency Protocol
protocol NetworkService {
func fetchData(from url: URL, completion: @escaping (Data?, Error?) -> Void)
}
URLSession Servisi:
// URLSession Implementation
class URLSessionNetworkService: NetworkService {
func fetchData(from url: URL, completion: @escaping (Data?, Error?) -> Void)
URLSession.shared.dataTask(with: url) { data, _, error in
completion(data, error)
}.resume()
}
}
Alamofire Servisi :
// Alamofire Implementation
class AlamofireNetworkService: NetworkService {
func fetchData(from url: URL, completion: @escaping (Data?, Error?) -> Void) {
AF.request(url).responseData { response in
switch response.result {
case .success(let data):
completion(data, nil)
case .failure(let error):
completion(nil, error)
}
}
}
}
View Model
class ViewModel: ObservableObject {
@Published var data: Data?
@Published var error: Error?
private let networkService: NetworkService
init(networkService: NetworkService) {
self.networkService = networkService
fetchData()
}
func fetchData() {
guard let url = URL(string: "https://example.com") else { return }
networkService.fetchData(from: url) { [weak self] data, error in
DispatchQueue.main.async {
self?.data = data
self?.error = error
}
}
}
}
Dependency Injection
struct ContentView: View {
@StateObject var viewModel: ViewModel
init() {
let networkService: NetworkService = URLSessionNetworkService() // veya AlamofireNetworkService()
let viewModel = ViewModel(networkService: networkService)
_viewModel = StateObject(wrappedValue: viewModel)
}
var body: some View {
Text("Data: \(String(data: viewModel.data ?? Data(), encoding: .utf8) ?? "Veri Yok!")")
.onAppear {
viewModel.fetchData()
}
}
}
Bu örnekte, NetworkManager
sınıfı, URLSession
veya Alamofire gibi ağ işlemlerini yapan sınıfların üzerine inşa edilmiştir. Daha sonra bu NetworkManager sınıfını ViewModel içinde veya başka bir yerde kullanabilirsiniz.
Not: _viewModel = StateObject(wrappedValue: viewModel)
_viewModel
adında bir @StateObject
özelliği tanımlanıyor ve bu özellik viewModel
adındaki bir ViewModel örneği ile başlatılıyor. Bu, ViewModel’inizin ömrü boyunca aynı örneği kullanmasını sağlar ve bu nesnenin otomatik olarak SwiftUI tarafından yönetilmesini sağlar. Yani, bu özellik SwiftUI tarafından otomatik olarak yönetilen bir ViewModel referansıdır ve SwiftUI’nin ViewModel’i değiştirmesi gerektiğinde otomatik olarak güncellenir.