Feature Flags en Swift : comment activer des fonctionnalités sans nouvelle build et sans casser la production
Imaginez : vous déployez un nouveau thème sombre, et les utilisateurs signalent que le texte devient illisible. Ou vous ajoutez un algorithme de recommandations complexe qui rame sur les anciens iPhone. Dans le scénario classique, vous corrigez le code, compilez une build, passez la revue, attendez l'App Store — 24 heures ou plus. Pendant tout ce temps, le bug est en production.
Les Feature flags (ou feature toggles) sont une technique qui permet d'activer ou de désactiver des fonctionnalités de l'application sans déployer de nouveau code. Il s'agit essentiellement d'opérateurs conditionnels qui vérifient la valeur d'un flag, cette valeur étant stockée à distance — sur un serveur ou dans Remote Config. Un seul interrupteur et la fonctionnalité apparaît pour tout le monde ou disparaît en quelques secondes.
Dans cet article, nous allons voir comment implémenter les feature flags en Swift, quels patterns utiliser, et comment ne pas vous tirer une balle dans le pied. C'est parti !
Pourquoi les feature flags sont-ils utiles dans le développement iOS
Beaucoup pensent que les feature flags ne servent que pour les tests A/B. En réalité, les cas d'usage sont bien plus nombreux :
- Déploiements canary (canary releases) — vous activez une nouvelle fonctionnalité pour 5% des utilisateurs, surveillez les crashs, et si tout va bien, vous la déployez pour tout le monde.
- Kill switches — si quelque chose tourne mal, vous désactivez simplement la fonctionnalité à distance, sans rollback de build.
- Déploiement progressif — vous montrez la fonctionnalité d'abord sur iOS 17+, puis sur les versions plus anciennes.
- Fonctionnalités payantes — vous masquez les fonctionnalités premium derrière un abonnement, en gérant les flags côté backend.
- Expériences et tests A/B — vous testez des hypothèses sur de vrais utilisateurs, sans créer de branches séparées.
C'est particulièrement pertinent pour les projets Swift, où le binaire est compilé une fois puis reste dans le store. Sans feature flags, vous ne pouvez pas réagir rapidement aux problèmes — seulement via une nouvelle version.
Architecture des feature flags en Swift
Une implémentation simple est un dictionnaire [String: Bool] provenant du serveur. Mais dans un projet en production, il est préférable de créer une abstraction solide. Voici les composants clés :
- FeatureFlagProvider — la source de données (Remote Config, votre API, fichier local).
- FeatureFlagManager — un singleton ou service qui met en cache les flags et les fournit aux vues.
- FeatureFlagKey — un enum avec des clés typées pour éviter de disperser des chaînes dans le code.
Écrivons une implémentation simple mais fonctionnelle en Swift.
Étape 1. Définir un enum avec les clés
enum FeatureFlagKey: String, CaseIterable { case darkMode = "dark_mode" case newOnboarding = "new_onboarding" case premiumAnalytics = "premium_analytics" case experimentalFeed = "experimental_feed"}Utiliser un enum plutôt que des chaînes garantit que vous ne ferez pas de faute de frappe dans le nom du flag. CaseIterable sera utile pour un écran de débogage.
Étape 2. Provider — récupérer les flags depuis Firebase Remote Config
import FirebaseRemoteConfig
final class RemoteConfigProvider: FeatureFlagProvider { private let remoteConfig = RemoteConfig.remoteConfig() func fetchFlags(completion: @escaping ([String: Bool]) -> Void) { remoteConfig.fetch(withExpirationDuration: 3600) { status, error in if status == .success { self.remoteConfig.activate { _, _ in let flags = FeatureFlagKey.allCases.reduce(into: [String: Bool]()) { result, key in result[key.rawValue] = self.remoteConfig.configValue(forKey: key.rawValue).boolValue } completion(flags) } } else { print("Failed to fetch remote config: \\(error?.localizedDescription ?? "")")