Sobes.tech
Middle

Avez-vous déjà utilisé la bibliothèque Combine dans vos projets?

sobes.tech IA

Réponse de l'IA

Oui, je l'ai utilisé.

L'utilisation principale de Combine dans mes projets concerne le traitement d'événements asynchrones, tels que :

  • Requêtes réseau : traitement des réponses API, transformation des données, gestion des erreurs.
  • Modifications des éléments UI : réaction aux actions de l'utilisateur, changements dans les champs de texte, glissements.
  • Traitement des données locales : suivi des modifications dans les bases de données (par exemple, Core Data), notifications de FileManager.
  • Création de flux de données réactifs dans l'architecture MVVM pour le binding entre la vue et le ViewModel.

Avantages de l'utilisation de Combine :

  1. Réduction de la quantité de code et amélioration de sa lisibilité lors du travail avec des opérations asynchrones.
  2. Gestion centralisée des erreurs et annulation des opérations.
  3. Composition et transformation faciles des flux de données avec des opérateurs.
  4. Intégration native avec les frameworks Apple (SwiftUI, Core Data, URLSession).

Exemple d'utilisation de Combine pour une requête réseau :

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) // Extraction des données du tuple (data, response)
        .decode(type: APIResult.self, decoder: JSONDecoder()) // Décodage des données
        .receive(on: DispatchQueue.main) // Passage au thread principal pour la mise à jour de l'UI
        .eraseToAnyPublisher() // Suppression du type spécifique pour la simplicité
}

// Exemple d'abonnement
let cancellable = fetchData(from: URL(string: "https://api.example.com/data")!)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            print("Requête terminée avec succès")
        case .failure(let error):
            print("Erreur de requête : \(error.localizedDescription)")
        }
    }, receiveValue: { result in
        print("Données reçues : \(result.value)")
    })
// Il faut conserver la référence à cancellable pour que l'abonnement reste actif

J'ai également utilisé Combine pour lier des propriétés dans MVVM :

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

    private var cancellables = Set<AnyCancellable>()

    init() {
        $text
            .map { $0.count > 0 } // Transformation du texte en valeur booléenne
            .assign(to: &$isValid) // Assignation du résultat à la propriété isValid
    }
}

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

    private var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Binding du UITextField au ViewModel
        NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: textView)
            .compactMap { ($0.object as? UITextField)?.text }
            .assign(to: \.text, on: viewModel) // Assignation du texte au ViewModel

        // Binding du ViewModel au UILabel
        viewModel.$isValid
            .map { $0 ? "Valide" : "Invalide" }
            .assign(to: \.text, on: validationLabel) // Assignation du texte au UILabel
            .store(in: &cancellables) // Stockage de l'abonnement
    }
}

L'expérience avec Combine est positive, il simplifie considérablement la gestion de l'asynchronie par rapport aux approches plus anciennes (closures, delegates) dans des scénarios complexes.