# Feature-Flags im iOS SDK

`Pushwoosh.configure.featureFlags` stellt Ihrer iOS-App die [Feature-Flags](/de/product/audience-data-and-segmentation/feature-flags/) bereit, die für die Anwendung im Control Panel konfiguriert sind. Pushwoosh wertet die Flag-Regeln auf dem Server für das aktuelle Gerät und den aktuellen Benutzer aus, und das SDK liefert das Ergebnis: ob das Flag für dieses Gerät aktiviert ist und welche Eigenschaftswerte gelten.

<Aside type="tip" title="Beta-Funktion">
Feature-Flags befinden sich in der Beta-Phase und sind nur in Tarifen verfügbar, die sie enthalten. In anderen Tarifen gibt der Server keine Flags zurück, sodass jedes Flag auf den Standardwert zurückfällt, den Sie im Code übergeben.
</Aside>

## Voraussetzungen

* Pushwoosh iOS SDK 7.2.10 oder höher, integriert wie in der [iOS SDK Übersicht](/de/developer/pushwoosh-sdk/ios-sdk/) beschrieben. Feature-Flags sind in den erforderlichen Modulen `PushwooshFramework` und `PushwooshCore` enthalten, sodass Sie kein weiteres Modul hinzufügen müssen. Sie funktionieren in der iOS-App selbst. App-Erweiterungen, etwa eine Notification Service Extension, fordern nie Flags an.
* Mindestens ein Flag, das unter **Audience** → **Feature Flags** erstellt wurde. Sie benötigen seinen **Key** sowie die Schlüssel und Typen seiner Eigenschaften. Verwenden Sie die Schlüssel genau so, wie sie dort angezeigt werden, einschließlich Groß- und Kleinschreibung. Beispielsweise findet `get("New_Checkout")` kein Flag mit dem Schlüssel `new_checkout`.
* Wenn die App SDK-Anfragen über einen Reverse-Proxy sendet, muss dessen URL auf `json/1.3/` enden. Andernfalls fordert das SDK keine Flags an, und jedes Flag fällt auf Ihren Standardwert zurück.

## Ein Flag lesen

Übergeben Sie immer einen Standardwert. Er gilt, bis das SDK Flags für das Gerät hat, und immer dann, wenn das Flag nicht existiert, archiviert ist oder der Tarif keine Feature-Flags enthält.

```swift
import PushwooshFramework

let flags = Pushwoosh.configure.featureFlags

if let checkout = flags.get("new_checkout"), checkout.isEnabled {
    showNewCheckout(
        buttonColor: checkout.string(forProperty: "button_color", default: "blue") ?? "blue",
        maxItems: Int(checkout.number(forProperty: "max_items", default: 3))
    )
} else {
    showOldCheckout()
}
```

Um nur zu prüfen, ob das Flag aktiviert ist, verwenden Sie `isEnabled`:

```swift
let isNewCheckout = Pushwoosh.configure.featureFlags.isEnabled("new_checkout", default: false)
```

Rufen Sie in Objective-C `[PushwooshConfig featureFlags]` auf.

## Was ein Flag zurückgibt

`get(_:)` gibt ein `PWFeatureFlag`-Objekt zurück oder `nil`, wenn das SDK noch keine Flags für das Gerät hat oder das Flag nicht in der Antwort enthalten ist. Ein archiviertes Flag ist nicht in der Antwort enthalten. `get` liest nur die gespeicherten Flags und wartet nie auf das Netzwerk. Das Objekt hat folgende Eigenschaften:

| Eigenschaft | Typ | Beschreibung |
| :---- | :---- | :---- |
| `key` | String | Der Flag-Schlüssel. |
| `isEnabled` | Bool | Ob das Flag für dieses Gerät aktiviert ist. |
| `ruleId` | String | Die Regel, die das Ergebnis bestimmt hat, zum Beispiel `r_1a2b3c4d`. `default`, wenn keine Regel auf das Gerät zutraf, und eine leere Zeichenfolge, wenn das Flag per Kill-Switch abgeschaltet ist. |

Lesen Sie Eigenschaftswerte mit der Methode, die zum Eigenschaftstyp passt. Wenn das Flag deaktiviert ist, enthalten die Eigenschaften die im Control Panel festgelegten Standardwerte.

| Methode | Rückgabe |
| :---- | :---- |
| `string(forProperty:default:)` | Der Wert einer **String**-Eigenschaft oder Ihr Standardwert. |
| `number(forProperty:default:)` | Der Wert einer **Number**-Eigenschaft als `Double` oder Ihr Standardwert. |
| `bool(forProperty:default:)` | Der Wert einer **Boolean**-Eigenschaft oder Ihr Standardwert. |
| `jsonObject(forProperty:)` | Der Wert einer **JSON**-Eigenschaft, die ein Objekt enthält, als Dictionary oder `nil`. |
| `jsonArray(forProperty:)` | Der Wert einer **JSON**-Eigenschaft, die ein Array enthält, oder `nil`. |

Jede Methode gibt Ihren Standardwert zurück, bei den JSON-Methoden `nil`, wenn die Eigenschaft fehlt oder einen Wert eines anderen Typs enthält.

`isEnabled(_:default:)` gibt den Standardwert zurück, wenn `get(_:)` `nil` zurückgibt.

<span id="keep-flags-up-to-date" />

## Flags aktuell halten

Das SDK speichert die letzte Antwort bis zu 24 Stunden auf dem Gerät. Die gespeicherten Flags sind nur für die User ID und den Application Code der App gültig, für die sie angefordert wurden. Das SDK aktualisiert sie:

* beim Start einer Sitzung, also wenn die App zum ersten Mal aktiv wird oder nach mindestens 30 Minuten im Hintergrund;
* stündlich, solange die App im Vordergrund ist;
* nachdem sich das Gerät für Push-Benachrichtigungen registriert hat, wenn die vorherige Anfrage vor der Registrierung gesendet wurde;
* direkt nach einer Änderung der User ID mit `setUserId`. Die gespeicherten Flags des vorherigen Benutzers werden verworfen, sodass ein neuer Benutzer sie nie sieht.

Um auf neue Werte zu reagieren, fügen Sie einen Listener hinzu, der `PWFeatureFlagsUpdateListener` implementiert. Seine Methode `featureFlagsDidUpdate()` wird auf dem Main Thread aufgerufen, nachdem eine Aktualisierung ein Flag geändert hat. Das SDK hält Listener schwach. Halten Sie eine starke Referenz auf Ihren Listener, sonst wird er freigegeben und nie aufgerufen:

```swift
final class CheckoutViewController: UIViewController, PWFeatureFlagsUpdateListener {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        Pushwoosh.configure.featureFlags.addUpdateListener(self)
    }

    override func viewWillDisappear(_ animated: Bool) {
        Pushwoosh.configure.featureFlags.removeUpdateListener(self)
        super.viewWillDisappear(animated)
    }

    func featureFlagsDidUpdate() {
        render()
    }
}
```

Um die Flags selbst anzufordern, zum Beispiel nach einer Aktion, die den Benutzer in ein anderes Segment verschieben kann, rufen Sie `refresh(completion:)` auf. Solange die gespeicherten Flags gültig sind, sendet die Methode höchstens eine Anfrage pro 5 Minuten und antwortet innerhalb dieses Zeitfensters mit den gespeicherten Flags. Die Completion läuft auf dem Main Thread:

```swift
Pushwoosh.configure.featureFlags.refresh { error in
    if let error = error as NSError? {
        let status = error.code
        // the stored flags, or your defaults, stay in effect
    }
    render()
}
```

Bei einem Fehler hat der Fehler die Domain `PWFeatureFlagsErrorDomain`, und sein `code` ist der HTTP-Status. Der Code ist `0`, wenn die Anfrage keine HTTP-Antwort erhalten hat oder nicht gesendet wurde, und `200`, wenn der Server geantwortet hat, die Antwort aber nicht verwendet werden konnte.

Um Aktualisierungen ohne das 5-Minuten-Limit zu testen, setzen Sie den Boolean-Schlüssel `Pushwoosh_FEATURE_FLAGS_DISABLE_THROTTLE` in der `Info.plist` auf `YES`.

Wenn Pushwoosh die Segmente des Geräts nicht rechtzeitig zuordnen kann, liefert es eine Teilantwort. Das SDK speichert sie nicht auf dem Gerät, und die nächste Aktualisierung liefert die vollständige Antwort.

Wenn ein Flag im Control Panel per Kill-Switch abgeschaltet wird, erhalten Geräte es bei der nächsten Aktualisierung deaktiviert mit den Standard-Eigenschaftswerten. Wenn das SDK den Server nicht erreichen kann, verwendet es die gespeicherten Flags weiter, bis sie 24 Stunden alt sind, und danach Ihre Standardwerte.

<span id="log-impressions" />

## Impressions protokollieren

Eine Impression teilt Pushwoosh mit, dass ein Benutzer den Code, den ein Flag steuert, tatsächlich erreicht hat, sodass Sie Benutzer, die die Funktion erhalten haben, mit denen vergleichen können, die sie nicht erhalten haben. Rufen Sie `logImpression(_:)` in dem Moment auf, in dem der Benutzer die Funktion oder ihre alte Version sieht, und zwar sowohl im aktivierten als auch im deaktivierten Zweig, denn Benutzer mit deaktiviertem Flag sind Ihre Vergleichsgruppe:

```swift
let flags = Pushwoosh.configure.featureFlags
let isOn = flags.isEnabled("new_checkout", default: false)
flags.logImpression("new_checkout")
if isOn {
    showNewCheckout()
} else {
    showOldCheckout()
}
```

Das SDK sendet das Event `PW_FeatureFlagImpression` mit diesen Attributen:

| Attribut | Typ | Wert |
| :---- | :---- | :---- |
| `flag_key` | string | Der Flag-Schlüssel. |
| `rule_id` | string | Die Regel, die das Ergebnis bestimmt hat, wie in `ruleId`. |
| `enabled` | boolean | Ob das Flag aktiviert war. |

Sie müssen das Event nicht vorab erstellen, denn Pushwoosh fügt `PW_FeatureFlagImpression` mit diesen Attributen unter **Audience** → **Events** hinzu, wenn die erste Impression eintrifft. Das SDK sendet pro Flag, Regel und Zustand eine Impression pro Sitzung und sendet nichts, wenn für den Schlüssel kein Flag vorhanden ist. Wenn das Senden fehlschlägt, sendet der nächste `logImpression`-Aufruf für das Flag sie erneut.

Mit Impressions können Marketer außerdem ein Segment der Benutzer erstellen, die die Funktion erreicht haben: den Zustand **hat die Funktion gesehen (30 Tage)** der [Feature-Flag-Bedingung](/de/product/audience-data-and-segmentation/feature-flags/#find-users-who-reached-a-feature).

## Methodenreferenz

`Pushwoosh.configure.featureFlags` hat diese Methoden:

| Methode | Beschreibung |
| :---- | :---- |
| `get(_:)` | Gibt das `PWFeatureFlag` für den Schlüssel zurück oder `nil`. Liest nur die gespeicherten Flags. |
| `isEnabled(_:default:)` | Gibt zurück, ob das Flag aktiviert ist, oder den Standardwert, wenn kein Flag vorhanden ist. |
| `refresh(completion:)` | Fordert die Flags an, höchstens einmal pro 5 Minuten, solange die gespeicherten Flags gültig sind. Die Completion erhält `nil` oder einen Fehler in `PWFeatureFlagsErrorDomain` und kann `nil` sein. |
| `addUpdateListener(_:)` | Ruft nach jeder Aktualisierung, die ein Flag geändert hat, die Methode `featureFlagsDidUpdate()` des Listeners auf. Der Listener wird schwach gehalten. |
| `removeUpdateListener(_:)` | Entfernt einen Listener, der mit `addUpdateListener(_:)` hinzugefügt wurde. |
| `logImpression(_:)` | Sendet ein `PW_FeatureFlagImpression`-Event für die aktuelle Regel und den aktuellen Zustand des Flags. |