TriggerProvider enables reactive updates when users enter or exit cohorts, allowing your app to respond to segment changes in real-time.
Overview
TriggerProvider provides:
Real-time cohort change notifications
Immediate callback when users enter/exit cohorts
Query-based triggers for complex conditions
User identity change monitoring
Use TriggerProvider instead of polling cohorts or activations for reactive behavior.
Accessing TriggerProvider
let triggerProvider = Permutive. shared . triggerProvider
Cohort Membership Triggers
Watch for changes in cohort membership:
import Permutive_iOS
class FeatureController {
private var premiumTrigger: TriggerAction?
func watchPremiumStatus () {
premiumTrigger = Permutive. shared . triggerProvider ?. action (
boolFor : [ "premium_subscriber" ],
action : { cohortId, isInCohort in
print ( "Cohort ' \( cohortId ) ' membership: \( isInCohort ) " )
if isInCohort {
self . enablePremiumFeatures ()
} else {
self . disablePremiumFeatures ()
}
}
)
}
private func enablePremiumFeatures () {
// Show premium content
}
private func disablePremiumFeatures () {
// Hide premium content
}
deinit {
// Release trigger to stop watching
premiumTrigger = nil
}
}
Watching Multiple Cohorts
class ContentPersonalizer {
private var contentTrigger: TriggerAction?
func watchUserInterests () {
contentTrigger = Permutive. shared . triggerProvider ?. action (
boolFor : [ "sports_enthusiast" , "tech_reader" , "news_follower" ],
action : { cohortId, isInCohort in
if isInCohort {
switch cohortId {
case "sports_enthusiast" :
self . boostSportsContent ()
case "tech_reader" :
self . boostTechContent ()
case "news_follower" :
self . boostNewsContent ()
default :
break
}
}
}
)
}
}
Query Triggers
For more complex data, use query triggers that return dictionaries or integers:
Dictionary Queries
class AnalyticsController {
private var queryTrigger: TriggerAction?
func watchComplexQueries () {
queryTrigger = Permutive. shared . triggerProvider ?. action (
dictionaryFor : [ "user_profile_query" , "engagement_metrics" ],
action : { queryId, result in
print ( "Query ' \( queryId ) ' returned: \( result ) " )
if queryId == "user_profile_query" ,
let preferences = result[ "preferences" ] as? [ String : Any ] {
self . applyUserPreferences (preferences)
}
}
)
}
}
Integer Queries
class ScoreController {
private var scoreTrigger: TriggerAction?
func watchEngagementScore () {
scoreTrigger = Permutive. shared . triggerProvider ?. action (
intFor : [ "engagement_score" ],
action : { queryId, score in
print ( "Engagement score: \( score ) " )
self . updateUIForScore (score)
}
)
}
private func updateUIForScore ( _ score : Int ) {
// Adjust UI based on engagement level
}
}
User ID Triggers
Monitor changes to the user identity:
class SessionController {
private var userIdTrigger: TriggerAction?
func watchUserIdentityChanges () {
userIdTrigger = Permutive. shared . triggerProvider ?. actionUpdateForUserIdentity { userId in
print ( "User identity changed to: \( userId ) " )
// Update analytics with new user ID
Analytics. setUserId (userId)
// Refresh user-specific data
self . refreshUserData ()
}
}
deinit {
userIdTrigger = nil
}
}
TriggerAction Lifecycle
You must maintain a strong reference to TriggerAction objects. Releasing the reference stops the trigger.
Keeping Triggers Active
class TriggerManager {
// Store triggers as instance properties
private var cohortTrigger: TriggerAction?
private var userIdTrigger: TriggerAction?
func setupTriggers () {
cohortTrigger = Permutive. shared . triggerProvider ?. action (
boolFor : [ "cohort" ],
action : { _ , _ in }
)
userIdTrigger = Permutive. shared . triggerProvider ?. actionUpdateForUserIdentity { _ in }
}
func stopWatching () {
// Explicitly release triggers
cohortTrigger = nil
userIdTrigger = nil
}
deinit {
// Automatically released when controller is deallocated
}
}
UIViewController Integration
class PersonalizedViewController : UIViewController {
private var cohortTrigger: TriggerAction?
override func viewDidLoad () {
super . viewDidLoad ()
// Start watching cohorts
cohortTrigger = Permutive. shared . triggerProvider ?. action (
boolFor : [ "premium_user" , "new_user" ],
action : { [ weak self ] cohortId, isInCohort in
DispatchQueue. main . async {
self ?. handleCohortChange ( cohortId : cohortId, isInCohort : isInCohort)
}
}
)
}
private func handleCohortChange ( cohortId : String , isInCohort : Bool ) {
switch cohortId {
case "premium_user" :
updatePremiumUI ( enabled : isInCohort)
case "new_user" :
showOnboarding ( isNew : isInCohort)
default :
break
}
}
deinit {
cohortTrigger = nil
}
}
SwiftUI Integration
import SwiftUI
import Permutive_iOS
struct PersonalizedView : View {
@StateObject private var triggerManager = TriggerManager ()
var body: some View {
VStack {
if triggerManager.isPremium {
PremiumContentView ()
} else {
StandardContentView ()
}
}
. onAppear {
triggerManager. startWatching ()
}
. onDisappear {
triggerManager. stopWatching ()
}
}
}
class TriggerManager : ObservableObject {
@Published var isPremium = false
private var trigger: TriggerAction?
func startWatching () {
trigger = Permutive. shared . triggerProvider ?. action (
boolFor : [ "premium_subscriber" ],
action : { [ weak self ] _ , isInCohort in
DispatchQueue. main . async {
self ?. isPremium = isInCohort
}
}
)
}
func stopWatching () {
trigger = nil
}
}
tvOS Considerations
tvOS Note: TriggerProvider works identically on tvOS. Use it to update UI elements based on cohort membership in your focus-based navigation.
Best Practices
Store TriggerAction references as instance properties
Use [weak self] in closures to avoid retain cycles
Dispatch UI updates to main thread
Release triggers when no longer needed
Group related cohorts in a single trigger
Don’t create triggers without storing the reference
Don’t create excessive numbers of triggers
Don’t perform heavy work in trigger callbacks
Don’t assume immediate callback on creation
Don’t forget to handle both enter and exit cases
Troubleshooting
Trigger callbacks not firing
Problem: No callbacks when cohort membership changes.Solutions:
Verify you’re storing a strong reference to TriggerAction
Check that cohort IDs match your dashboard
Enable debug logging to see cohort updates
Ensure SDK is initialized before creating triggers
Problem: Trigger worked initially but stopped.Cause: TriggerAction reference was released.Solution: Store TriggerAction as an instance property, not a local variable.
Problem: Callback fires but UI doesn’t change.Solution: Dispatch UI updates to main thread:DispatchQueue. main . async {
self . updateUI ()
}