Sobes.tech
Middle

Použili ste niekedy knižnicu Combine vo svojich projektoch?

sobes.tech AI

Odpoveď od AI

Da, koristio sam.

Glavna primena Combine u mojim projektima je povezana sa obradom asinhronih događaja, kao što su:

  • Mrežni zahtevi: Obrada odgovora od API-ja, transformacija podataka, obrada grešaka.
  • Promene u UI elementima: Reakcija na akcije korisnika, promene tekstualnih polja, klizači.
  • Obrada lokalnih podataka: Praćenje promena u bazama podataka (npr. Core Data), obaveštenja od FileManager-a.
  • Kreiranje reaktivnih tokova podataka u MVVM arhitekturi za povezivanje View sa ViewModel.

Prednosti korišćenja Combine:

  1. Smanjenje količine koda i poboljšanje čitljivosti pri radu sa asinhronim operacijama.
  2. Centralizovana obrada grešaka i otkazivanje operacija.
  3. Laka kompozicija i transformacija tokova podataka pomoću operatora.
  4. Nativna integracija sa Apple framework-ovima (SwiftUI, Core Data, URLSession).

Primer korišćenja Combine za mrežni zahtev:

import Combine
import Foundation

struct APIResult: Decodable {
    let value: String
}

func fetchData(from url: URL) -> AnyPublisher<APIResult, Error> {
    URLSession.shared.dataTaskPublisher(for: url)
        .map(\.data) // Izvlačenje podataka iz tuple-a (data, response)
        .decode(type: APIResult.self, decoder: JSONDecoder()) // Dekodiranje podataka
        .receive(on: DispatchQueue.main) // Prebacivanje na glavni thread za ažuriranje UI
        .eraseToAnyPublisher() // Sakrivanje tipova za jednostavnost
}

// Primer pretplate
let cancellable = fetchData(from: URL(string: "https://api.example.com/data")!)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            print("Zahtev uspešno završen")
        case .failure(let error):
            print("Greška u zahtevu: \(error.localizedDescription)")
        }
    }, receiveValue: { result in
        print("Primljeni podaci: \(result.value)")
    })
// cancellable treba sačuvati da bi pretplata ostala aktivna

Takođe sam koristio Combine za povezivanje svojstava u MVVM:

class ViewModel {
    @Published var text: String = ""
    @Published var isValid: Bool = false

    private var cancellables = Set<AnyCancellable>()

    init() {
        $text
            .map { $0.count > 0 } // Pretvaranje teksta u boolean
            .assign(to: &$isValid) // Dodeljivanje rezultata svojstvu isValid
    }
}

class ViewController: UIViewController {
    let textView = UITextField()
    let validationLabel = UILabel()
    let viewModel = ViewModel()

    private var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Povezivanje UITextField sa ViewModel
        NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: textView)
            .compactMap { ($0.object as? UITextField)?.text }
            .assign(to: \.text, on: viewModel) // Dodeljivanje teksta ViewModel-u

        // Povezivanje ViewModel-a sa UILabel-om
        viewModel.$isValid
            .map { $0 ? "Valid" : "Invalid" }
            .assign(to: \.text, on: validationLabel) // Dodeljivanje teksta UILabel-u
            .store(in: &cancellables) // Čuvanje pretplate
    }
}

Pozitivno iskustvo sa Combine je da značajno olakšava rad sa asinhronnošću u poređenju sa starijim pristupima (closures, delegate-i) u složenim scenarijima.