Conteneur d'injection de dépendances Swift : Swinject pour iOS/macOS

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Conteneur d'injection de dépendances pour Swift (iOS/macOS) : Swinject

Dans le développement moderne iOS et macOS avec Swift, les patrons architecturaux jouent un rôle clé dans la création d'un code maintenable et testable. L'un des outils les plus puissants pour implémenter le principe d'inversion des dépendances (Dependency Inversion Principle) est Swinject — un conteneur DI léger mais fonctionnel, écrit en Swift. Swinject permet de gérer de manière centralisée la création d'objets et leurs dépendances, libérant le développeur de la construction manuelle du graphe d'objets.



Qu'est-ce que l'injection de dépendances et pourquoi un conteneur ?

L'injection de dépendances (DI) est une technique par laquelle un objet reçoit ses dépendances de l'extérieur, plutôt que de les créer lui-même. Cela réduit le couplage du code et simplifie les tests unitaires. Cependant, dans les grands projets, l'injection manuelle des dépendances conduit à un code volumineux. C'est là qu'un conteneur DI intervient, qui :

  • Automatise la création et la liaison des objets
  • Gère la durée de vie des objets (singletons, nouvelles instances)
  • Facilite le remplacement des implémentations (par exemple, pour les tests)
  • Améliore la lisibilité et la maintenabilité du code


Installation de Swinject

Swinject peut être installé via Swift Package Manager, CocoaPods ou Carthage. Pour SPM, ajoutez dans Package.swift :

dependencies: [    .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0")]

Ou via CocoaPods :

pod 'Swinject', '~> 2.8'


Concepts clés de Swinject

La bibliothèque repose sur plusieurs composants essentiels :

  • Container — l'enregistreur et résolveur principal des dépendances
  • Service — le type qui est enregistré (généralement un protocole ou une classe)
  • Component — l'implémentation concrète du service
  • Scope — détermine la durée de vie de l'objet (transient, graph, container, weak)


Exemple pratique : enregistrement et résolution des dépendances

Considérons un scénario typique — une application avec un service d'authentification et un contrôleur qui l'utilise.

// Protocole du serviceprotocol AuthServiceProtocol {    func login(username: String, password: String) -> Bool}

// Implémentationclass AuthService: AuthServiceProtocol { func login(username: String, password: String) -> Bool { // Logique d'authentification return username == "admin" && password == "1234" }}

// Contrôleur dépendant de AuthServiceProtocolclass LoginViewController { private let authService: AuthServiceProtocol // Injection via l'initialiseur init(authService: AuthServiceProtocol) { self.authService = authService } func authenticate(user: String, pass: String) { if authService.login(username: user, password: pass) { print("Connexion réussie") } else { print("Données incorrectes") } }}

// Configuration du conteneurlet container = Container()container.register(AuthServiceProtocol.self) { _ in AuthService() }container.register(LoginViewController.self) { r in LoginViewController(authService: r.resolve(AuthServiceProtocol.self)!)}

// Utilisationlet controller = container.resolve(LoginViewController.self)!controller.authenticate(user: "admin", pass: "1234") // Connexion réussie


Gestion de la durée de vie (Scopes)

Swinject prend en charge quatre scopes intégrés :

  • .transient — une nouvelle instance est créée à chaque fois (par défaut)
  • .graph — une instance par graphe de résolution (utilisé par défaut dans la plupart des cas)
  • .container — singleton dans le cadre du conteneur
  • .weak — référence faible, l'objet

Recommendations