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

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

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

\n\n

L'injection de dépendances (DI) est l'un des principes clés du SOLID, permettant de créer un code faiblement couplé, testable et évolutif. Dans le monde Swift pour le développement iOS et macOS, l'une des bibliothèques les plus populaires implémentant la DI est Swinject. C'est un conteneur d'injection de dépendances léger mais puissant, qui simplifie la gestion des objets et de leur cycle de vie.

\n\n

Dans cet article, nous allons détailler comment fonctionne Swinject, comment l'installer et l'utiliser dans des projets réels.

\n\n

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

\n

L'injection de dépendances 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 améliore la flexibilité et simplifie les tests. Un conteneur DI (comme Swinject) automatise le processus de création et de liaison des objets, évitant au développeur d'écrire du code boilerplate.

\n\n

Installation de Swinject

\n

Swinject peut être installé via Swift Package Manager, CocoaPods ou Carthage. Examinons la méthode la plus moderne — SPM :

\n\n
// Dans Xcode : File → Swift Packages → Add Package Dependency\n// URL : https://github.com/Swinject/Swinject.git\n// Version : à partir de 2.8.0
\n\n

Ou ajoutez dans Package.swift :

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

Composants principaux de Swinject

\n
    \n
  • Container — l'objet principal dans lequel les dépendances sont enregistrées et résolues.
  • \n
  • Service — le type (protocole ou classe) que nous souhaitons injecter.
  • \n
  • Registration — le processus de liaison d'une abstraction (protocole) avec une implémentation concrète.
  • \n
  • Scope — gère le cycle de vie de l'objet (transient, singleton, etc.).
  • \n
\n\n

Exemple d'utilisation de base

\n

Supposons que nous ayons un protocole NetworkServiceProtocol et son implémentation NetworkService :

\n\n
import Swinject\n\nprotocol NetworkServiceProtocol {\n    func fetchData() -> String\n}\n\nclass NetworkService: NetworkServiceProtocol {\n    func fetchData() -> String {\n        return "Données reçues"\n    }\n}\n\n// Création du conteneur\nlet container = Container()\n\n// Enregistrement de la dépendance\ncontainer.register(NetworkServiceProtocol.self) { _ in NetworkService() }\n\n// Résolution (obtention) de l'instance\nlet service = container.resolve(NetworkServiceProtocol.self)!\nprint(service.fetchData()) // "Données reçues"
\n\n

Injection de dépendances dans un ViewController (iOS)

\n

Le plus souvent, Swinject est utilisé pour injecter des services dans les contrôleurs. Voici un exemple avec un view-model :

\n\n
import Swinject\n\n// Protocole et implémentation du view-model\nprotocol UserViewModelProtocol {\n    func getUsers() -> [String]\n}\n\nclass UserViewModel: UserViewModelProtocol {\n    private let networkService: NetworkServiceProtocol\n    \n    init(networkService: NetworkServiceProtocol) {\n        self.networkService = networkService\n    }\n    \n    func getUsers() -> [String] {\n        // Utilisation de networkService pour le chargement\n        return ["Alice", "Bob"]\n    }\n}\n\n// Enregistrement dans le conteneur\ncontainer.register(UserViewModelProtocol.self) { resolver in\n    let network = resolver.resolve(NetworkServiceProtocol.self)!\n    return UserViewModel(networkService: network)\n}\n\n// Utilisation dans le contrôleur\nclass UsersViewController: UIViewController {\n    var viewModel: UserViewModelProtocol?\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        viewModel = container.resolve(UserViewModelProtocol.self)\n        print(viewModel?.getUsers() ?? [])\n    }\n}
\n\n

Cycles de vie des objets (Scopes)

\n

Swinject prend en charge plusieurs scopes :

\n
    \n
  • .transient
  • \n

Recommendations