Skip to content

Latest commit

 

History

History
186 lines (154 loc) · 5.54 KB

File metadata and controls

186 lines (154 loc) · 5.54 KB

SwiftUI Generic Service with Alamofire and URLSession

Swift Platform Platform License

Bu örnek proje, SwiftUI kullanarak Dependency Injection (DI) ve Singleton tasarım desenini, MVVM ile Generic Network Manager oluşturmayı gösterir.

Proje, Alamofire veya URLSession ile DummyJSON API'den verileri çekmeyi amaçlar.

  • Desing Patterns
  • MVVM
  • Alamofire Api Servisi
  • URLSession Servisi
  • Auth Mekanizması
  • Generic Network Layer
  • UI Tasarımı
  • 3. parti kütüphane entegrasyonları

Product Model

  struct ProductResponse: Codable {
    let products: [Product]
}

struct Product: Codable, Identifiable {
    let id: Int?
    let title, description: String
    let price: Int
    let discountPercentage, rating: Double
    let stock: Int
    let brand, category: String
    let thumbnail: String
    let images: [String]
}

ApiServiceProtocol Protocol

ApiServiceProtocol adlı bir protocol, ağ çağrıları yapmak için gerekli işlevselliği tanımlar.

protocol ApiServiceProtocol {
    func getRequest<T: Codable>(endpoint: URL, parameters: [String: Any]?, completion: @escaping(Result<T, Error>) -> Void )
    func addRequest<T: Codable>(endpoint: URL, data: T, completion: @escaping(Result<Void, Error>) -> Void)
    func updateRequest<T: Codable>(endpoint: URL, data: T, completion: @escaping(Result<Void, Error>) -> Void)
    func deleteRequest(endpoint: URL, completion: @escaping(Result<Void, Error>) -> Void)
}

AlamofireApiService

AlamofireApiService adlı sınıf, ApiService protocolünü uygular ve bu sınıfı singleton olarak tasarlar.

class AlamofireApiService: ApiServiceProtocol {
    
    private init() { }
    
    static let shared = AlamofireApiService()
    
    func getRequest<T: Codable>(endpoint: URL, parameters: [String: Any]?, completion: @escaping (Result<T, Error>) -> Void) {
        AF.request(endpoint, method: .get, parameters: parameters)
        .validate()
        .responseDecodable(of: T.self) { response in
            switch response.result {
            case .success(let value):
                completion(.success(value))
            case .failure(let error):
                completion(.failure(error))
            }
        }
    }

    // postRequest()
    // updateReques()
    // deleteRequest()

ProductApiService

ProductApiService adlı sınıf, ağ işlemleri için DI ile kendisine tanımlanacak olan (ApiService protokülü uygulayan) api servis ile işlemlerini gerçekleştirir.

class ProductApiService{
    
    let apiService: ApiServiceProtocol
    
    init(apiService: ApiServiceProtocol) {
        self.apiService = apiService
    }
    
    func getAllProducts(parameters: [String: Any]?, completion: @escaping (Result<[Product], Error>) -> Void ){ // tüm postları getirmek için
        apiService.getRequest(endpoint: APIConstants.getProductEndpoint, parameters: parameters) { (result: Result<ProductResponse, Error>) in
            switch result {
            case .success(let data):
                completion(.success(data.products))
            case .failure(let error):
                completion(.failure(error))
            }
        }
    }
}
// getProductById()
// createProduct()
// updateProduct()
// deleteProduct()

ProductViewModel

ProductViewModel, ürünleri çekmek ve ürün arayüzünü güncellemek için kullanılır. Dependency Injection kullanılarak ApiServiceProtocol enjekte edilir.

class ProductViewModel: ObservableObject {
    
    @Published var products: [Product] = []
    @Published var product: Product?
    @Published var isShowing: Bool = false
    @Published var isError: Bool = false
    @Published var title = ""
    @Published var message = ""
    
    let productApiService: ProductApiService
    
    init(productApiService: ProductApiService) {
        self.productApiService = productApiService
    }
    
    func fetchAllProducts(parameters: [String: Any]? = nil) {
        productApiService.getAllProducts(parameters: parameters) { result in
            switch result {
            case .success(let products):
                DispatchQueue.main.async {
                    self.products = products
                }
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }
}

// fetchProductById()
// addProduct()
// updateProduct()
// deleteProduct()

View ile Kullanımı

Dependency Injection kullanılarak ApiServiceProtocol singleton olarak ProductViewModel'e enjekte edilir ve bu ViewModel, ProductListView tarafından kullanılır.

struct ProductListView: View {
    
    @StateObject var viewModel: ProductViewModel
    init(apiService:  ApiServiceProtocol) {
        _viewModel = StateObject(wrappedValue: ProductViewModel(productApiService: .init(apiService: apiService)))
    }

    var body: some View {
        // ...
    }
}

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                ProductListView(apiService: AlamofireApiService.shared)
            }
            .navigationTitle("Products")
        }
    }
}

Özellikler

  • MVVM
  • Singleton
  • Dependency Injection
  • Generic Network Layer
  • Protocol Oriented Programming (POP)
  • Alamofire & URLSession
  • ContentUnavailableView
  • SDWebImage
  • SwipeActions
  • .searchable modifier
  • NavigationStack