Kraftfulla feature flags i Swift + iOS
Med feature flags kan du långsamt utrullning av en funktion, snarare än att göra en riskfylld big bang-lansering, och är extremt användbara när de används i en miljö med kontinuerlig integration och kontinuerlig leverans.


Men att bygga ett system för feature flags är vanligtvis inte ditt företags kärnkompetens och kan vara en distraktion från andra utvecklingsinsatser.
Jag heter Kody och är Developer Advocate på Optimizely. I det här blogginlägget i 8 steg visar jag hur man får ut värdet av kraftfulla feature flags genom att utrullning av en funktion kund för kund i Swift + iOS med hjälp av Optimizely Rollouts: en helt gratis produkt.
Obs: Om du inte har en iOS-applikation att testa med rekommenderar vi att du följer med den fullständiga källkoden i Hello World App.
Bonus: Jag kommer också att drifta en session om ämnet feature flags för mobilappar.
Steg för att rulla ut en funktion
1. Konfigurera gränssnittet för feature flags
Skapa ett gratis konto för Optimizely Rollouts här.
I utrullningsgränssnittet navigerar du till "Features > Create New Feature" och skapar en feature flag som heter "hello_world".
För att ansluta din "hello_world"-funktion till din applikation, hitta din SDK-nyckel. Navigera till "Settings" och kopiera SDK-nyckelns värde.
2. Installera Optimizely Swift-paketet
Med Optimizely Swift-paketet kan du ställa in funktionsväxlingar från din kodbas med hjälp av Swift. Om du inte redan har ett Xcode-projekt för att följa med, skapar du en ny app med en enda vy i Xcode. Ställ in appen så att den använder Storyboard och Swift som språk. Nu när du har ditt Xcode-projekt klart ska vi installera Optimizely SDK.
Använda Swift Package Manager
I Xcode klickar du på Arkiv > Swift-paket > Lägg till paketberoende
Klistra sedan in'https://github.com/optimizely/swift-sdk.git'i fältet URL för paketförvaret:
Följ Xcode-dialogrutan för att slutföra installationen av Optimizely Swift-paketet.
Initialisera SDK
För att använda Optimizely Swift-paketet importerar du först paketet högst upp i din AppDelegate.swift-fil och initierar sedan SDK i funktionen 'didFinishLaunchingWithOptions'. Ersätt koden i din AppDelegate.swift-fil med koden nedan och kom ihåg att klistra in din Optimizely SDK-nyckel .
import UIKit import Optimizely @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { // Bygg 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("Initieringen av Optimizely SDK misslyckades: \(error)") case .success: print("Optimizely SDK initialiserades framgångsrikt!") } } return true } }
I det här exemplet ställer vi in 30 så att SDK frågar efter ändringar i funktionskonfigurationen var 30:e sekund. Detta är helt enkelt för att demonstrera funktionsväxlingen snabbare (standardfrekvensen är var 10:e minut).
Obs: Vi rekommenderar inte att du anpassar intervallet för att ladda ner om du inte har ett specifikt behov av det.
3. Implementera funktionen
För att implementera vår "hello_world"-funktion använder vi Xcodes Interface Builder för att lägga till en enda knapp som presenterar en varning. Vi använder vår feature flag för att diktera innehållet i varningen.
Lägg till knappen
Lägg till en knapp med namnet "Click Me!" i gränssnittet och centrera den.
Anslut knappen till vykontrollern
- Öppna ViewController.swift
- Kopiera och klistra in koden nedan i ViewController-klassen.
@IBAction func showMessage(sender: UIButton) { var enabled = false let alertController = UIAlertController(title: "Alert", message: enabled ? "Hej världen!" : "Inget att se här...", 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) }
Koppla knappen i användargränssnittet till funktionen ovan (med hjälp av storyboard: öppna Main.storyboard och med "control"-tangenten nedtryckt, klicka och dra från knappen till view controller-ikonen längst upp till vänster på iPhone. En meny fälls ner, klicka på showMessageWithSender)'
Koppla knappen till funktionen "hello_world"
Nu när vi har kopplat knappen i gränssnittet till vår funktion i ViewController.swift, kommer funktionen att anropas när knappen klickas. Men du kanske har märkt att det i funktionen finns en variabel som heter "enabled" som används i ett ternärt uttryck för att växla meddelandet i varningen samt texten på knappen för att avfärda varningen. Följ stegen nedan för att ansluta till OptimizelyClient för att dynamiskt ställa in värdet på 'enabled' baserat på användarId och konfigurationen av Optimizely feature flag.
- För att importera Optimizely-klienten för användning i vykontrollern klistrar du in följande i ViewController-klassen ovanför knappfunktionen:
- let delegate = UIApplication.shared.delegate as! AppDelegat
För att använda Optimizely-klienten för att ställa in värdet på enabled, klistra in följande i knappfunktionen nära toppen under enabled-variabeln:let userId = "user123" let attributes: [String: Any] = [ "customerId": 123, // Attribut som används för målgruppsbaserad utrullning "isVip": true, ] enabled = delegate.optimizely.isFeatureEnabled(featureKey: "hello_world", userId: userId, attributes: attributes) print("Funktionen är aktiverad? - \(enabled) för userId: \(userId)")
Parametrarna till isFeatureEnabled(featureKey, userId, attributes) är följande:
- featureKey: namnet på funktionen för att ansluta den här metoden till Optimizely UI.
- userId: används för att rulla ut till en slumpmässig andel av användarna, vi kommer inte att använda den här parametern i det här inlägget, lämna som en icke-tom sträng för tillfället.
- attributes: används för en målgruppsinriktad utrullning bland dina användare. Du kommer att använda dessa attribut för att målgruppsinrikta din funktion till specifika grupper av användare med början i steg 5.
Returvärdet, isEnabled, är en boolean som anger om funktionen var aktiverad eller inte aktiverad för dessa ingångar.
Den fullständiga koden för vår ViewController.swift bör nu se ut som följer:
Test + Learn: Experimentation
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, // Attribut som används för målgruppsbaserad utrullning "isVip": true, ] enabled = delegate.optimizely.isFeatureEnabled(featureKey: "hello_world", userId: userId, attributes: attributes) print("Funktionen är aktiverad? - \(enabled) för userId: \(userId)") let alertController = UIAlertController(title: "Alert", meddelande: aktiverad ? "Hej världen!" : "Inget att se här...", 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. Slå på funktionsväxlingen!
Tryck på alternativ+kommando+S för att spara alla filer och klicka sedan på knappen "build and run" längst upp till vänster för att köra appen i Xcode. I iOS-simulatorn klickar du på knappen för att visa varningen och du kommer att märka att du inte fick funktionen hello_world. Detta beror på att funktionen inte är aktiverad, vilket innebär att den är avstängd för alla användare av din app.
Så här slår du på funktionen i Optimizely:
- Navigera till Funktioner
- Klicka på funktionen "hello_world
- Slå på funktionen och se till att den är inställd på 100% (se skärmdump nedan)
- Klicka på Save för att spara dina ändringar
Vänta 30 sekunder och klicka sedan på knappen "Click Me" utan att starta om appen som körs för att se varningen om att ändringarna i Optimizely One har trätt i kraft. Varningen bör nu visa meddelandet "Hello World!" som indikerar att funktionen är funktionsväxlad.
Du har nu framgångsrikt lanserat din funktion bakom en feature flags, men den är tillgänglig för alla. Nästa steg är att aktivera målgruppsinriktning för att visa din funktion endast för en specifik delmängd av användare för att möjliggöra det verkliga värdet av att rulla ut en funktion kund för kund.
5. Skapa ett attribut för customerId
För att målgruppsinrikta din funktion baserat på de "attribut" som du angav till isFeatureEnabled API i steg 3 måste du skapa dessa attribut i Rollouts UI. Gör det med attributet "customerId" till att börja med:
- Navigera till målgrupper -> attribut
- Klicka på 'Skapa nytt attribut...'
- Ge attributnyckeln namnet 'customerId'
- Klicka på "Save Attribute" för att spara dina ändringar
6. Skapa och lägg till en beta-publik
Nu ska vi skapa en målgrupp för att ange vilka customerIds som ska få tillgång till din funktion.
- Navigera till Funktioner
- Klicka på din "hello_world"-funktion
- Bläddra ner till Audiences
- Klicka på "Skapa ny målgrupp...
- Namnge målgruppen '[hello_world] Beta Users'
- Dra och släpp ditt customerId-attribut i målgruppens villkor
- Ändra rullgardinsmenyn "har valfritt värde" till "Antal är lika med" med värdet 123
- Klicka på "Spara målgrupp
Lägg till målgruppen i din funktion genom att klicka på +-knappen bredvid din nyskapade målgrupp. Bläddra sedan nedåt och klicka på "spara".
Nu när du har lagt till målgruppen i din funktion är betaversionen igång. För närvarande visas din funktion endast för kunder med customerId 123, vilket är vad du tillhandahöll isFeatureEnabled API i parametern userAttributes.
Som ett test för att verifiera kan du ändra ditt customerId till 456, spara och se hur funktionen stängs av eftersom du inte uppfyller villkoren för målgruppsinriktning.
7. Lägg till användare i betaversionen
Om du vill lägga till fler kunder i din beta-publik redigerar du publikdefinitionen för att lägga till eller ta bort användare från betaversionen:
- Klicka på "+"-tecknet och spara för att lägga till betaanvändare
- Klicka på "x"-tecknet och spara för att ta bort beta-användare
I följande skärmdumpsexempel har tre kunder lagts till i betaversionen. Kunder med id: 123, 456 och 789, kommer nu att ha tillgång till funktionen "hello_world".
8. Starta funktionen
När du har aktiverat din funktion för tillräckligt många kunder för att de ska kunna njuta av den nya användarupplevelsen kan du bestämma dig för att det är säkert att lansera din funktion för alla kunder.
När du är redo att lansera din funktion från betaversionen följer du dessa steg:
- Ta bort målgruppen från din funktion
- Säkerställ att utrullningen är konfigurerad till 100
- Spara funktionen
Funktionen är nu tillgänglig för alla och du har framgångsrikt rullat ut "hello_world"-funktionen kund för kund med hjälp av gratis feature flags från Optimizely Rollouts in Swift + iOS!
9. Bonus: Lyssna efter konfigurationsändringar för Feature Flags
Hittills har vi visat hur man skickar en bucket till användare när de vidtar en åtgärd i iOS-appen. Du kan också lägga till aviseringslyssnare i Optimizely-klienten för att koppla in relevanta händelser. Du kan till exempel lyssna på "datafileListener" för att dynamiskt ändra innehållet i appen när fjärranslutna ändringar görs i konfigurationen av dina funktioner i Optimizely. Anropa nedanstående funktion addListeners() innan optimizely.start() för att lägga till lyssnarna.
func addListeners() { let notificationCenter = optimizely.notificationCenter //notification avfyras när ett värde returneras av isFeatureEnabled function call _ = notificationCenter?.addDecisionNotificationListener(decisionListener: { (type, userId, attributes, decisionInfo) in print("Mottog beslutsmeddelande: \(typ) \(userId) \(String(beskriver: attribut)) \(decisionInfo)") }) //avisering som avfyras när SDK frågar efter en ny datafil och datafilen har ändrats _ = notificationCenter?.addDatafileChangeNotificationListener(datafileListener: { (_) in print("datafilen ändrades!") }) }
Nästa steg
Även om den här bloggen handlade om utrullning av funktioner kund för kund, möjliggör feature flags ytterligare användningsfall som att inte förlita sig på långlivade feature branches, skapa ett behörighetssystem eller möjliggöra produktdriven A/B-testning på backend.
En annan fördel med feature flags är att du kan slå på och av funktioner när din app är live i App Store, utan att behöva gå igenom Apples långa granskningsprocess!
På Optimizely använder vi feature flags för alla dessa användningsområden och mer därtill.
Hoppas att detta var till hjälp! Ge feedback om du har någon. Jag hoppas att jag har lyckats spara några av ditt teams utvecklingsresurser genom att göra det möjligt för dig att utnyttja kraften i feature flags med vår gratis feature flagging-produkt: Optimizely Rollouts.