Callbacks

Because Leanplum variables and resources are retrieved from the server asynchronously after start, you need to wait for the values to be downloaded before using them in your code. The proper way to do this is to use one of the callbacks provided by our SDK.

The SDK will use locally-cached values, if available, and changes will only be synced on start or forceContentUpdate.

You can use callbacks multiple times across different classes in your app. However, where you place the callback may influence when it is executed. If you call one after the necessary variables (and/or files) for that callback have been synced, the code in the callback will just execute again immediately.

Timing

All callbacks are executed on start, regardless of whether the file(s) or variable(s) have changed. The distinction between our callbacks is their behavior on forceContentUpdate — namely, which files or variables will trigger the callback. You can watch a single variable, a single file, all variables, or all variables and all files.

❗️

In order to use the forceContentUpdate method, you will be required to use version 1.3.0+ of our JavaScript SDK to use the .

📘

Make sure that you are testing the forceContentUpdate method, while the app is built in production mode. When the app is built in dev mode, all Leanplum variables are synced in real time, which speeds up testing, but differs from the production behavior.

callbackexecuted when
After Leanplum start* start finishes.
When a variable is ready start finishes.
forceContentUpdate finishes and a specific variable has changed.
When all variables are ready start finishes.
forceContentUpdate finishes and any variable has changed.
When a file is ready start finishes.
forceContentUpdate finishes and a specific file has changed.
When all variables and files are ready start finishes.
forceContentUpdate finishes and a file or variable has changed.

After Leanplum start

This callback is executed only when the start call finishes and all variables and files are returned from the Leanplum server. It will not be executed on forceContentUpdate.

You can use this callback with a splash screen to wait and then load a new view after start finishes, so you don't have to worry about checking when your variables have their values.

// Add a callback.
Leanplum.onStartResponse{ (success) in
  // Insert code here.
}
Leanplum.start()

// Or, add a responder that will be executed as a callback.
Leanplum.addStartResponseResponder(self, with: #selector(mySelector(success:)))

func mySelector(success:Bool){
  // Insert code here.
}
// Add a callback.
[Leanplum onStartResponse:^(BOOL success) {
  // Insert code here.
}];
[Leanplum start];

// Or, add a responder that will be executed as a callback.
[Leanplum addStartResponseResponder:self withSelector:@selector(mySelector:)];

- (void)mySelector:(BOOL) success {
  // Insert code here.
}
// Add a new callback.
Leanplum.addStartResponseHandler(new StartCallback() {
  @Override
  public void onResponse(boolean b) {
    // Insert code here.
  }
});
// Add a callback.
Leanplum.Started += delegate(bool success) {
  // Insert code here.
};
Leanplum.Start();
// Add a callback.
Leanplum.addStartResponseHandler(function(success) {
  // Insert code here.
});
Leanplum.start();
Leanplum.onStartResponse((success: boolean) => {
  if (success) {
    // handle success
  } else {
    // handle failure
  }
});

When a variable is ready

This callback is executed after start every time, but only after forceContentUpdate if a specific variable has changed (not supported on JavaScript).

//Define the variable and set the name and value using the Var class.
var startLabel = Var(name: "startLabel", string: "Start")

// Then wrap your code in the callback.
startLabel.onValueChanged({
  self.startButton.titleLabel.text = self.startLabel.stringValue
  // Insert code here.
})
// Define the variable with the correct macro.
DEFINE_VAR_STRING(startLabel, @"Start");

// Then wrap your code in the callback.
[startLabel onValueChanged:^{
  self.startButton.titleLabel.text = startLabel.stringValue;
  // Insert code here.
}];
// Define the file variable with Var.define.
Var<String> startLabel = Var.define("welcomeMessage", "Start");

// Then add a handler and pass it a new callback.
startLabel.addValueChangedHandler(new VariableCallback<String>() {
  @Override
  public void handle(Var<String> var) {
    // Insert code here.
  }
});
// Define the variable.
Var<string> startLabel = Var<string>.Define("startLabel", "Start");  

// Then, insert your code in a delegate added to ValueChanged.
startLabel.ValueChanged += delegate {
  // Insert code here.
};
const func = () => {};
const variableName = 'stringVar';
const value = await Leanplum.onValueChanged(variableName, func);

🚧

This callback does not wait for files to finish downloading. If you are using file variables, see below.

When all variables are ready

This callback is executed after start every time, but only after forceContentUpdate if any variable has changed.

You can use forceContentUpdate (except in JavaScript) to re-sync with Leanplum during an active session.

Leanplum.onVariablesChanged { () in
  // Insert code here.
}
[Leanplum onVariablesChanged:^() {
  // Insert code here.
}];
Leanplum.addVariablesChangedHandler(new VariablesChangedCallback() {
  @Override
  public void variablesChanged() {
    // Insert code here.
  }
});
Leanplum.VariablesChanged += delegate {
  // Insert code here.
};
Leanplum.addVariablesChangedHandler(function(success){
  // Insert code here.
});
const func = () => {};
Leanplum.onVariablesChanged(func);

🚧

This callback does not wait for files to finish downloading. If you are using file variables, see below.

When a file is ready

This callback will execute after start every time, but only after forceContentUpdate when the file has changed. If the file is unchanged, no download will occur and the callback will not be executed.

//Define the variable and set the name and value using the Var class
var goldstarImage = Var(name: "goldStar", file: "gold_star.png")

goldStar.onFileReady { () in
  goldStarImage = UIImage.init(contentsOfFile: (goldStar.fileValue())!)
}
// Define the file variable with the correct macro.
DEFINE_VAR_FILE(goldStar, @"gold_star.png");

[goldStar onFileReady:^() {
  goldStarImage = [UIImage imageWithContentsOfFile:[goldStar fileValue]];
}];
// Define the file variable with defineAsset.
Var<String> kitten = Var.defineAsset("kitten", "kitten.jpg");

kitten.addFileReadyHandler(new VariableCallback<String>() {
  @Override
  public void handle(Var<String> variable) {
    // Insert code here.
  }
});

When all variables and files are ready

You can also wait for all variable changes and file downloads. This callback will execute after start, but only after forceContentUpdate if any of your Leanplum variables or files have changed.

// Add a callback.
Leanplum.onVariablesChangedAndNoDownloadsPending { () in
  // Insert code here.
}

// Or, add a responder to be executed as a callback.
Leanplum.addVariablesChangedAndNoDownloadsPendingResponder(self, with: #selector(self.customResponder))

func customResponder() {
  // Insert code here.
}
// Add a callback.
[Leanplum onVariablesChangedAndNoDownloadsPending:^() {
  goldStarImage = [UIImage imageWithContentsOfFile:[goldStar fileValue]];
}];
  
// Or, add a responder to be executed as a callback.
[Leanplum addVariablesChangedAndNoDownloadsPendingResponder:self withSelector:@selector(customResponder)];

- (void)customResponder {
  // Insert code here.
}
// Add a callback.
Leanplum.addVariablesChangedAndNoDownloadsPendingHandler(new VariablesChangedCallback() {
    @Override
    public void variablesChanged() {
        // Insert code here.
    }
});
// Add a callback.
Leanplum.VariablesChangedAndNoDownloadsPending += delegate {
  // Insert code here.
};
Leanplum.onVariablesChangedAndNoDownloadsPending(() => {
  console.log('onVariablesChangedAndNoDownloadsPending');
});

Testing callbacks in development mode

When you're testing your app, it's often useful to tweak values and see the result instantly. If you use Variable callbacks, your variables will change immediately after you change them in the Leanplum dashboard.

If you want to mimic your users' experience and don't want to see real-time changes when testing, use the start callback, which is only triggered the first time variables receive their values on start.

Leanplum will tell you if it couldn't connect to the server, in which case the values will be whatever they were the last time the app was run (or their default values set in the code if the app hasn't been run yet).