Feature flags в iOS SDK
Pushwoosh.configure.featureFlags передаёт вашему iOS-приложению feature flags, настроенные для приложения в Панели управления. Pushwoosh вычисляет правила флага на сервере для текущего устройства и пользователя, а SDK возвращает результат: включён ли флаг для этого устройства и какие значения свойств действуют.
Требования
Anchor link to- Pushwoosh iOS SDK 7.2.10 или новее, интегрированный, как описано в обзоре iOS SDK. Feature flags входят в обязательные модули
PushwooshFrameworkиPushwooshCore, поэтому добавлять другой модуль не нужно. Они работают в самом iOS-приложении. Расширения приложения, например Notification Service Extension, никогда не запрашивают флаги. - Хотя бы один флаг, созданный в Audience → Feature Flags. Вам понадобятся его Key, а также ключи и типы его свойств. Используйте ключи точно в том виде, в каком они указаны там, с учётом регистра. Например,
get("New_Checkout")не найдёт флаг с ключомnew_checkout. - Если приложение отправляет запросы SDK через обратный прокси, его URL должен заканчиваться на
json/1.3/. Иначе SDK не запрашивает флаги, и каждый флаг принимает ваше значение по умолчанию.
Чтение флага
Anchor link toВсегда передавайте значение по умолчанию. Оно действует, пока у SDK нет флагов для устройства, а также когда флаг не существует, архивирован или тариф не включает feature flags.
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()}Чтобы только проверить, включён ли флаг, используйте isEnabled:
let isNewCheckout = Pushwoosh.configure.featureFlags.isEnabled("new_checkout", default: false)В Objective-C вызывайте [PushwooshConfig featureFlags].
Что возвращает флаг
Anchor link toget(_:) возвращает объект PWFeatureFlag или nil, если у SDK ещё нет флагов для устройства или флага нет в ответе. Архивированного флага в ответе нет. get читает только сохранённые флаги и никогда не ждёт сети. У объекта есть следующие свойства:
| Свойство | Тип | Описание |
|---|---|---|
key | String | Ключ флага. |
isEnabled | Bool | Включён ли флаг для этого устройства. |
ruleId | String | Правило, определившее результат, например r_1a2b3c4d. default, если устройству не подошло ни одно правило, и пустая строка, если флаг аварийно отключён (killed). |
Считывайте значения свойств методом, который соответствует типу свойства. Когда флаг выключен, свойства содержат значения по умолчанию, заданные в Панели управления.
| Метод | Возвращает |
|---|---|
string(forProperty:default:) | Значение свойства типа String или ваше значение по умолчанию. |
number(forProperty:default:) | Значение свойства типа Number в виде Double или ваше значение по умолчанию. |
bool(forProperty:default:) | Значение свойства типа Boolean или ваше значение по умолчанию. |
jsonObject(forProperty:) | Значение свойства типа JSON, содержащего объект, в виде словаря или nil. |
jsonArray(forProperty:) | Значение свойства типа JSON, содержащего массив, или nil. |
Каждый метод возвращает ваше значение по умолчанию (для JSON-методов — nil), если свойство отсутствует или содержит значение другого типа.
isEnabled(_:default:) возвращает значение по умолчанию, когда get(_:) возвращает nil.
Актуальность флагов
Anchor link toSDK хранит последний ответ на устройстве до 24 часов. Сохранённые флаги действительны только для того User ID и Application Code приложения, для которых они были запрошены. SDK обновляет их:
- при старте сессии, то есть когда приложение становится активным впервые или после не менее 30 минут в фоне;
- каждый час, пока приложение на переднем плане;
- после регистрации устройства для push-уведомлений, если предыдущий запрос был отправлен до регистрации;
- сразу после смены User ID через
setUserId. Сохранённые флаги предыдущего пользователя удаляются, поэтому новый пользователь их никогда не увидит.
Чтобы реагировать на новые значения, добавьте слушатель, реализующий PWFeatureFlagsUpdateListener. Его метод featureFlagsDidUpdate() вызывается в главном потоке после обновления, которое изменило какой-либо флаг. SDK хранит слушатели по слабой ссылке. Держите на свой слушатель сильную ссылку, иначе он будет освобождён и никогда не вызовется:
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() }}Чтобы запросить флаги самостоятельно, например после действия, которое может перевести пользователя в другой сегмент, вызовите refresh(completion:). Пока сохранённые флаги действительны, метод отправляет не более одного запроса за 5 минут, а в пределах этого окна отвечает сохранёнными флагами. Completion выполняется в главном потоке:
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()}При ошибке у неё домен PWFeatureFlagsErrorDomain, а её code — HTTP-статус. Код равен 0, если запрос не получил HTTP-ответа или не был отправлен, и 200, если сервер ответил, но ответ не удалось использовать.
Чтобы тестировать обновления без 5-минутного ограничения, задайте в Info.plist ключу типа Boolean Pushwoosh_FEATURE_FLAGS_DISABLE_THROTTLE значение YES.
Если Pushwoosh не успевает определить сегменты устройства, он возвращает частичный ответ. SDK не сохраняет его на устройстве, и следующее обновление приносит полный ответ.
Когда флаг аварийно отключают (kill) в Панели управления, устройства при следующем обновлении получают его выключенным со значениями свойств по умолчанию. Когда SDK не может связаться с сервером, он продолжает использовать сохранённые флаги, пока им не исполнится 24 часа, а после этого — ваши значения по умолчанию.
Запись показов
Anchor link toПоказ (impression) сообщает Pushwoosh, что пользователь действительно дошёл до кода, которым управляет флаг, чтобы вы могли сравнить пользователей, получивших функцию, с теми, кто её не получил. Вызывайте logImpression(_:) в момент, когда пользователь видит функцию или её старую версию, — и во включённой, и в выключенной ветке, потому что пользователи с выключенным флагом и есть ваша группа сравнения:
let flags = Pushwoosh.configure.featureFlagslet isOn = flags.isEnabled("new_checkout", default: false)flags.logImpression("new_checkout")if isOn { showNewCheckout()} else { showOldCheckout()}SDK отправляет событие PW_FeatureFlagImpression со следующими атрибутами:
| Атрибут | Тип | Значение |
|---|---|---|
flag_key | string | Ключ флага. |
rule_id | string | Правило, определившее результат, как в ruleId. |
enabled | boolean | Был ли флаг включён. |
Создавать событие заранее не нужно: Pushwoosh добавляет PW_FeatureFlagImpression с этими атрибутами в Audience → Events, когда приходит первый показ. SDK отправляет один показ на флаг, правило и состояние за сессию и ничего не отправляет, если для ключа нет флага. Если отправить не удалось, следующий вызов logImpression для этого флага отправит показ повторно.
Показы также позволяют маркетологам построить сегмент пользователей, дошедших до функции: состояние видел фичу (30 дней) в условии по feature flag.
Справочник методов
Anchor link toУ Pushwoosh.configure.featureFlags есть следующие методы:
| Метод | Описание |
|---|---|
get(_:) | Возвращает PWFeatureFlag для ключа или nil. Читает только сохранённые флаги. |
isEnabled(_:default:) | Возвращает, включён ли флаг, или значение по умолчанию, если флага нет. |
refresh(completion:) | Запрашивает флаги не чаще одного раза за 5 минут, пока сохранённые флаги действительны. Completion получает nil или ошибку в PWFeatureFlagsErrorDomain и может быть nil. |
addUpdateListener(_:) | Вызывает featureFlagsDidUpdate() слушателя после каждого обновления, которое изменило флаг. Слушатель хранится по слабой ссылке. |
removeUpdateListener(_:) | Удаляет слушатель, добавленный через addUpdateListener(_:). |
logImpression(_:) | Отправляет событие PW_FeatureFlagImpression для текущего правила и состояния флага. |