Leistungsstarke Feature Flags in Swift + iOS

Kody O'ConnellKody O'Connell
30. März 2022

Feature Flags ermöglichen es Ihnen, eine Funktion schrittweise auszurollen, anstatt einen riskanten Big-Bang-Launch durchzuführen, und sind äußerst hilfreich, wenn sie in einer Umgebung mit Continuous Integration und Continuous Delivery eingesetzt werden.

Der Aufbau eines Feature-Flagging-Systems gehört jedoch in der Regel nicht zur Kernkompetenz Ihres Unternehmens und kann von anderen Entwicklungsbemühungen ablenken.

Ich bin Kody, Developer Advocate bei Optimizely. In diesem 8-stufigen Blogbeitrag zeige ich, wie Sie den Wert leistungsstarker Feature Flags nutzen, indem Sie eine Funktion Kunde für Kunde in Swift + iOS mit Optimizely Rollouts ausrollen: einem völlig kostenlosen Produkt.

Hinweis: Falls Sie keine iOS-Anwendung zum Testen haben, empfehlen wir, dem vollständigen Quellcode in der Hello World App zu folgen.

Bonus-Hinweis: Ich veranstalte außerdem eine Session zum Thema Feature Flags für mobile Apps.

Schritte zum Ausrollen einer Funktion

1. Richten Sie die Feature-Flag-Oberfläche ein

Erstellen Sie hier ein kostenloses Optimizely-Rollouts-Konto.

Navigieren Sie in der Rollouts-Oberfläche zu „Features > Create New Feature“ und erstellen Sie ein Feature Flag namens „hello_world“.


Um Ihre Funktion „hello_world“ mit Ihrer Anwendung zu verbinden, suchen Sie Ihren SDK-Key. Navigieren Sie zu „Settings“ und kopieren Sie den Wert des SDK-Keys.

2. Installieren Sie das Optimizely Swift Package

Das Optimizely Swift Package ermöglicht es Ihnen, Feature-Toggles innerhalb Ihrer Codebasis mit Swift einzurichten. Falls Sie noch kein Xcode-Projekt zum Mitverfolgen eingerichtet haben, erstellen Sie eine neue Single-View-App in Xcode. Stellen Sie die App auf Storyboard ein und legen Sie Swift als Sprache fest. Da Ihr Xcode-Projekt nun bereit ist, installieren wir das Optimizely SDK. 

Mit dem Swift Package Manager

Klicken Sie in Xcode auf File > Swift Packages > Add Package Dependency

Fügen Sie dann „https://github.com/optimizely/swift-sdk.git“ in das Feld für die URL des Package-Repositorys ein: 

Folgen Sie dem Xcode-Dialog, um die Installation des Optimizely Swift Package abzuschließen.

Initialisieren Sie das SDK

Um das Optimizely Swift Package zu verwenden, importieren Sie zunächst das Package am Anfang Ihrer Datei AppDelegate.swift und initialisieren Sie dann das SDK in der Funktion „didFinishLaunchingWithOptions“. Ersetzen Sie den Code in Ihrer Datei AppDelegate.swift durch den untenstehenden Code und denken Sie daran, Ihren Optimizely SDK-Key einzufügen. 

import UIKit import Optimizely @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { // Build OptimizelyClient let optimizely = OptimizelyClient(sdkKey: "REPLACE_WITH_SDK_KEY", periodicDownloadInterval: 30) func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { optimizely.start { result in switch result { case .failure(let error): print("Optimizely SDK initiliazation failed: \(error)") case .success: print("Optimizely SDK initialized successfully!") } } return true } }  


In diesem Beispiel setzen wir den Wert auf 30, damit das SDK alle 30 Sekunden nach Änderungen an der Feature-Konfiguration abfragt. Dies dient lediglich dazu, das Feature-Toggling schneller zu demonstrieren (die Standardfrequenz beträgt alle 10 Minuten). 

Hinweis: Wir empfehlen nicht, das Download-Intervall anzupassen, es sei denn, Sie haben einen konkreten Bedarf dafür. 

3. Implementieren Sie die Funktion

Um unsere Funktion „hello_world“ zu implementieren, verwenden wir den Interface Builder von Xcode, um eine einzelne Schaltfläche hinzuzufügen, die einen Alert anzeigt. Wir nutzen unser Feature Flag, um den Inhalt des Alerts zu bestimmen.

Fügen Sie die Schaltfläche hinzu

Fügen Sie der UI eine Schaltfläche namens „Click Me!“ hinzu und zentrieren Sie sie.

Verbinden Sie die Schaltfläche mit dem View Controller

  • Öffnen Sie ViewController.swift
  • Kopieren Sie den untenstehenden Code und fügen Sie ihn in die ViewController-Klasse ein.
  • @IBAction func showMessage(sender: UIButton) { var enabled = false let alertController = UIAlertController(title: "Alert", message: enabled ? "Hello World!" : "Nothing to see here...", preferredStyle: UIAlertController.Style.alert) if enabled { alertController.addAction(UIAlertAction(title: "Hello!", style: UIAlertAction.Style.default, handler: nil)) } else { alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil)) } present(alertController, animated: true, completion: nil) }
    Verbinden Sie die Schaltfläche in der UI mit der obigen Funktion (mit dem Storyboard: Öffnen Sie Main.storyboard und klicken Sie bei gedrückter „control“-Taste vom Button zum View-Controller-Symbol oben links am iPhone und ziehen Sie. Ein Menü klappt herunter, klicken Sie auf showMessageWithSender)’

Verbinden Sie die Schaltfläche mit der Funktion „hello_world“

Da wir nun die Schaltfläche in der Oberfläche mit unserer Funktion in der ViewController.swift verbunden haben, wird die Funktion bei jedem Klick auf die Schaltfläche aufgerufen. Möglicherweise ist Ihnen aufgefallen, dass in der Funktion eine Variable namens „enabled“ in einem ternären Ausdruck verwendet wird, um die Nachricht des Alerts sowie den Text der Schaltfläche zum Schließen des Alerts umzuschalten. Folgen Sie den untenstehenden Schritten, um eine Verbindung zum OptimizelyClient herzustellen und den Wert von „enabled“ dynamisch basierend auf der userId und der Konfiguration des Optimizely Feature Flags festzulegen.

  • Um den Optimizely-Client zur Verwendung im View Controller zu importieren, fügen Sie Folgendes in die ViewController-Klasse über der Button-Funktion ein:
  • let delegate = UIApplication.shared.delegate as! AppDelegate
    Um den Optimizely-Client zum Festlegen des Werts von enabled zu verwenden, fügen Sie Folgendes in der Button-Funktion oben unterhalb der Variablen enabled ein:
    let userId = "user123" let attributes: [String: Any] = [ "customerId": 123, // Attributes used for targeted audience-based rollout "isVip": true, ] enabled = delegate.optimizely.isFeatureEnabled(featureKey: "hello_world", userId: userId, attributes: attributes) print("Feature is enabled? - \(enabled) for userId: \(userId)")

Die Parameter von isFeatureEnabled(featureKey, userId, attributes) sind die folgenden:

  • featureKey: Name der Funktion, um diese Methode mit der Optimizely-UI zu verbinden.
  • userId: wird verwendet, um die Funktion an einen zufälligen Prozentsatz der Nutzer auszurollen; wir verwenden diesen Parameter in diesem Beitrag nicht, lassen Sie ihn vorerst als nicht-leeren String.
  • attributes: wird für einen gezielten Rollout über Ihre Nutzer verwendet. Sie verwenden diese Attribute, um Ihre Funktion ab Schritt 5 auf bestimmte Nutzergruppen auszurichten.

Der Rückgabewert isEnabled ist ein boolescher Wert, der angibt, ob die Funktion für diese Eingaben aktiviert war oder nicht.

Der vollständige Code für unsere ViewController.swift sollte nun wie folgt aussehen:

import UIKit class ViewController: UIViewController { let delegate = UIApplication.shared.delegate as! AppDelegate @IBAction func showMessage(sender: UIButton) { var enabled = false let userId = "user123" let attributes: [String: Any] = [ "customerId": 123, // Attributes used for targeted audience-based rollout "isVip": true, ] enabled = delegate.optimizely.isFeatureEnabled(featureKey: "hello_world", userId: userId, attributes: attributes) print("Feature is enabled? - \(enabled) for userId: \(userId)") let alertController = UIAlertController(title: "Alert", message: enabled ? "Hello World!" : "Nothing to see here...", preferredStyle: UIAlertController.Style.alert) if enabled { alertController.addAction(UIAlertAction(title: "Hello!", style: UIAlertAction.Style.default, handler: nil)) } else { alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil)) } present(alertController, animated: true, completion: nil) } }

4. Aktivieren Sie den Feature-Toggle!

Drücken Sie Option+Command+S, um alle Dateien zu speichern, und klicken Sie dann oben links auf die Schaltfläche „build and run“, um die App in Xcode auszuführen. Klicken Sie im iOS-Simulator auf die Schaltfläche, um den Alert anzuzeigen, und Sie werden feststellen, dass Sie die hello_world-Funktion nicht erhalten haben. Das liegt daran, dass die Funktion nicht aktiviert ist, was bedeutet, dass sie für alle Nutzer Ihrer App deaktiviert ist.

So aktivieren Sie die Funktion in Optimizely:

  • Navigieren Sie zu Features
  • Klicken Sie auf die Funktion „hello_world“
  • Schalten Sie die Funktion ein und stellen Sie sicher, dass sie auf 100 % eingestellt ist (siehe Screenshot unten)
  • Klicken Sie auf Save, um Ihre Änderungen zu speichern

Warten Sie 30 Sekunden und klicken Sie dann, ohne Ihre laufende App neu zu starten, auf die Schaltfläche „Click Me“, um zu sehen, wie der Alert mit den wirksam gewordenen Optimizely-Änderungen angezeigt wird. Der Alert sollte nun die Nachricht „Hello World!“ anzeigen, was darauf hinweist, dass die Funktion aktiviert ist.

Sie haben Ihre Funktion nun erfolgreich hinter einem Feature Flag gestartet, aber sie ist für alle verfügbar. Der nächste Schritt besteht darin, das Targeting zu aktivieren, um Ihre Funktion nur einer bestimmten Teilmenge von Nutzern anzuzeigen, um den wahren Wert eines Funktions-Rollouts Kunde für Kunde zu erschließen. 

5. Erstellen Sie ein Attribut für customerId

Um Ihre Funktion basierend auf den „attributes“ auszurichten, die Sie in Schritt 3 der isFeatureEnabled-API übergeben haben, müssen Sie diese Attribute in der Rollouts-UI erstellen. Tun Sie dies zunächst mit dem Attribut „customerId“:

  • Navigieren Sie zu Audiences -> Attributes
  • Klicken Sie auf „Create New Attribute…“
  • Benennen Sie den Attributschlüssel „customerId“
  • Klicken Sie auf „Save Attribute“, um Ihre Änderungen zu speichern

6. Erstellen und fügen Sie eine Beta-Audience hinzu

Erstellen wir nun eine Audience, um anzugeben, welche customerIds Zugriff auf Ihre Funktion erhalten.

  • Navigieren Sie zu Features
  • Klicken Sie auf Ihre Funktion „hello_world“
  • Scrollen Sie nach unten zu Audiences
  • Klicken Sie auf „Create New Audience…“
  • Benennen Sie die Audience „[hello_world] Beta Users“
  • Ziehen Sie Ihr customerId-Attribut per Drag-and-Drop in die Audience-Bedingungen
  • Ändern Sie das Dropdown „has any value“ auf „Number equals“ mit dem Wert 123
  • Klicken Sie auf „Save Audience“

Fügen Sie die Audience zu Ihrer Funktion hinzu, indem Sie auf die Schaltfläche + neben Ihrer neu erstellten Audience klicken. Scrollen Sie dann nach unten und klicken Sie auf „save“.

Da Sie die Audience nun zu Ihrer Funktion hinzugefügt haben, ist die Beta aktiv und läuft. Zu diesem Zeitpunkt wird Ihre Funktion nur für Kunden mit der customerId 123 angezeigt, also dem Wert, den Sie der isFeatureEnabled-API im Parameter userAttributes übergeben haben.

Zur Überprüfung können Sie testweise Ihre customerId auf 456 ändern, speichern und beobachten, wie die Funktion deaktiviert wird, weil Sie die Targeting-Bedingungen nicht erfüllen. 

7. Fügen Sie Nutzer zur Beta hinzu

Um weitere Kunden zu Ihrer Beta-Audience hinzuzufügen, bearbeiten Sie die Audience-Definition, um Nutzer zur Beta hinzuzufügen oder daraus zu entfernen:

  • Klicken Sie auf das „+“-Zeichen und speichern Sie, um Beta-Nutzer hinzuzufügen
  • Klicken Sie auf das „x“-Zeichen und speichern Sie, um Beta-Nutzer zu entfernen

Im folgenden Screenshot-Beispiel wurden drei Kunden zur Beta hinzugefügt. Kunden mit den IDs 123, 456 und 789 haben nun Zugriff auf die Funktion „hello_world“.

8. Starten Sie die Funktion

Nachdem Sie Ihre Funktion für genügend Kunden aktiviert haben, damit diese das neue Nutzererlebnis genießen können, entscheiden Sie möglicherweise, dass es sicher ist, Ihre Funktion für alle Kunden zu starten.

Sobald Sie bereit sind, Ihre Funktion aus der Beta zu starten, folgen Sie diesen Schritten:

  • Entfernen Sie die Audience aus Ihrer Funktion
  • Stellen Sie sicher, dass der Rollout auf 100 % konfiguriert ist
  • Speichern Sie die Funktion

Die Funktion ist nun für alle verfügbar und Sie haben die Funktion „hello_world“ erfolgreich Kunde für Kunde mit kostenlosen Feature Flags von Optimizely Rollouts in Swift + iOS ausgerollt!

9. Bonus: Hören Sie auf Änderungen der Feature-Flag-Konfiguration

Bisher haben wir gezeigt, wie Nutzer eingeordnet werden, wenn sie in der iOS-App eine Aktion ausführen. Sie können dem Optimizely-Client auch Notification-Listener hinzufügen, um sich in relevante Events einzuklinken. Sie könnten beispielsweise auf den „datafileListener“ hören, um App-Inhalte dynamisch zu ändern, wenn an der Konfiguration Ihrer Funktionen in Optimizely Remote-Änderungen vorgenommen werden. Rufen Sie die untenstehende Funktion addListeners() vor optimizely.start() auf, um die Listener hinzuzufügen.

func addListeners() { let notificationCenter = optimizely.notificationCenter //notification fired when a value is returned by isFeatureEnabled function call _ = notificationCenter?.addDecisionNotificationListener(decisionListener: { (type, userId, attributes, decisionInfo) in print("Received decision notification: \(type) \(userId) \(String(describing: attributes)) \(decisionInfo)") }) //notification fired when SDK polls for a new datafile and the datafile has changed _ = notificationCenter?.addDatafileChangeNotificationListener(datafileListener: { (_) in print("data file did change!") }) }

Nächste Schritte

Obwohl dieser Blog Rollouts Kunde für Kunde behandelt hat, ermöglichen Feature Flags zusätzliche Anwendungsfälle, etwa nicht auf langlebige Feature-Branches angewiesen zu sein, ein Berechtigungssystem zu erstellen oder produktgetriebenes A/B-Testing im Backend zu ermöglichen.

Ein weiterer Vorteil von Feature Flags ist, dass Sie Funktionen ein- und ausschalten können, sobald Ihre App im App Store live ist, ohne den langwierigen Prüfprozess von Apple durchlaufen zu müssen!

Bei Optimizely nutzen wir Feature Flags für all diese Anwendungsfälle und mehr.

Ich hoffe, das war hilfreich! Geben Sie Feedback, falls Sie welches haben. Ich hoffe, es ist mir gelungen, einige Entwicklungsressourcen Ihres Teams zu sparen, indem ich es Ihnen ermögliche, die Leistungsfähigkeit von Feature Flags mit unserem kostenlosen Feature-Flagging-Produkt zu nutzen: Optimizely Rollouts.