iOS SDK
With the Kameleoon iOS (Swift) SDK, you can run experiments and activate feature flags on native mobile iOS applications. Integrating our SDK into your Swift apps is easy, and its footprint (memory and network usage) is low.
Getting started: For help getting started, see the developer guide.
Changelog: Latest version of the Swift SDK: 4.10.0 Changelog.
SDK methods: For the full reference documentation of the iOS SDK methods, see the reference section.
Developer guide
Follow these steps to install and configure the Kameleoon iOS SDK in your application for the first time.
Getting started
Starter kit
If you're just getting started with Kameleoon, we provide a starter kit and demo application to test the SDK and learn how it works. The starter kit includes a fully configured app with examples demonstrating how you might use the SDK methods in your app. You can find the starter kit, the demo application and detailed instructions on how to use it at Starter kit for iOS
Prerequisites
- Use Swift version 5.0 or higher on the iOS platform. There is no planned support for earlier iOS applications (including earlier Swift versions and Objective-C apps). We provide a Universal Framework version compatible both with x86_64 (for the iOS Simulator) and ARM (for production deployment into the App Store).
Installation
You can install the iOS SDK using CocoaPods or Swift Package Manager:
- CocoaPods
- Swift Package Manager
With CocoaPods, paste the following code in your Podfile and replace YOUR_TARGET_NAME
with the value for your app:
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'kameleoonClient'
end
Then, in a command prompt, in the Podfile
directory, run the install command:
pod install
With Swift Package Manager, add a package dependency to your Xcode project. Select File > Swift Packages > Add Package Dependency and enter the repository URL: https://github.com/Kameleoon/client-swift
.
Alternatively, you can modify your Package.swift
file directly:
dependencies: [
.package(url: "https://github.com/Kameleoon/client-swift.git", from("3.0.3"))
]
Additional configuration
To customize the SDK behavior, create a kameleoon-client-swift.plist
configuration file in the root directory of your Xcode project. You can also download a sample configuration file.
These are the keys you can set:
refresh_interval_minute
(optional): Specifies the frequency, in minutes, that active experiments and feature flags are fetched from the Kameleoon servers. The initial fetch is performed on the first application launch and subsequent fetches are processed at the defined refresh interval. Once you launch an experiment, pause the experiment, or stop the experiment, the change won't propagate to each of your visitors' iOS devices until their next refresh. This means if you set the refresh interval to 30 minutes, it may take up to 30 minutes before all devices receive the update. If not specified, the default interval is 60 minutes.data_expiration_interval_minute
: Designates the predefined time period, in minutes, that the SDK stores the visitor and their associated data. Each data instance is evaluated individually. This allows you to set the amount of time the SDK saves the data before automatically deleting it. If no interval is specified, the SDK does not automatically delete data from the device. The default value isDate.distantFuture
.default_timeout_millisecond
: Specifies the refresh interval, in minutes, that the SDK fetches the configuration for the active experiments and feature flags. The value determines the maximum time it takes to propagate changes, such as activating or deactivating feature flags or launching experiments, to your production servers. If left unspecified, the default interval is set to 60 minutes. Additionally, we offer a streaming mode that uses server-sent events (SSE) to push new configurations to the SDK automatically and apply new configurations in real-time, without any delays.tracking_interval_millisecond
: this specifies the interval for tracking requests, in milliseconds. All visitors who were evaluated for any feature flag or had data flushed will be included in this tracking request, which is performed once per interval. The minimum value is100
ms and the maximum value is1000
ms, which is also the default value.environment
(optional): For customers using multi-environment experimentation and feature flagging, this option specifies which feature flag configuration to use. By default, each feature flag has the optionsproduction
,staging
,development
. If not specified, the default value isproduction
. More information.is_unique_identifier
(optional): Indicates that the specifiedvisitorCode
is a unique identifier. If not provided, the default value is false.
If you specify a visitorCode
and set the isUniqueIdentifier
parameter to true
, the SDK methods use the visitorCode
value as the unique visitor identifier, which is useful for cross-device experimentation. The SDK links the flushed data with the visitor that is associated with the specified identifier.
The isUniqueIdentifier
can be useful in other edge-case scenarios, such as when you can't access the anonymous visitorCode
that was originally assigned to the visitor, but you do have access to an internal ID that is connected to the anonymous visitor using session merging capabilities.
Initialize the Kameleoon Client
After you've the SDK in your application and set up the app properties, the next step is to create the Kameleoon Client. A Client is a singleton object that acts as a bridge between your application and the Kameleoon platform. It includes all the methods and properties you need to run an experiment.
import kameleoonClient
let visitorCode = "visitorCode"
let siteCode = "a8st4f59bj"
do {
// pass client configuration as an argument
let config = try KameleoonClientConfig(
clientId: "clientId", // optional
clientSecret: "clientSecret", // optional
refreshIntervalMinute: 15, // optional, 60 minutes by default
dataExpirationIntervalMinute: 60*24*365, // optional, `Data.distantFuture` by default
defaultTimeoutMillisecond: 10_000, // optional, 10_000 milliseconds by default
trackingIntervalMillisecond: 500, // optional, 1000 milliseconds by default
environment: "production", // optional
isUniqueIdentifier: true, // optional, false by default
)
let kameleoonClient = try KameleoonClientFactory.create(
siteCode: siteCode,
visitorCode: visitorCode, // optional
config: config // optional
)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
// Indicates that provided site code is empty
} catch {
// Unexpected error occurred
}
do {
// read client configuration from a file 'kameleoon-client-swift.plist'
// visitor code isn't provided, so SDK generates a random visitor code which it will use in the future
let kameleoonClient = try KameleoonClientFactory.create(siteCode: siteCode)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch {
// Unexpected error occurred
}
The KameleoonClientFactory.create()
method initializes the client, but the client is not immediately ready for use. The client must retrieve the current configuration of experiments and feature flags (along with their traffic repartition) from a Kameleoon remote server. This requires the client to have network access, which is not always available. Until the Kameleoon Client is fully ready, you should not attempt to run other methods in the Kameleoon iOS SDK. After the client fetches the first configuration of feature flags, it periodically refreshes the configuration. If the refresh fails for any reason, the Kameleoon client continues to function using the previous configuration.
You can use the .ready
public getter to check if the Kameleoon client initialization is finished.
Alternatively, you can use a helper callback to encapsulate the logic of experiment triggering and variation implementation. The best approach (.ready
or callback) depends on your preferences and use case. We recommend using .ready
when you expect that the SDK will already be ready for use. For example, if you are running an experiment on a dialog that would be accessible only after a few seconds or minutes of navigation within the app. We recommend using the callback when there is a high probability that the SDK is still initializing when the experiment is accessible. For example, an experiment that is visible at the launch of the app should use a callback that makes the application wait until either the SDK is ready or a specified timeout has expired.
It's your responsibility as the app developer to ensure the client is ready before calling any methods. A good practice is to always assume that the app user should be left out of the experiment if the Kameleoon client is not yet ready. This is actually easy to do, because this corresponds to the implementation of the default reference variation logic. For example, as shown in the code sample above.
You're now ready to implement feature management and features flags. See the Reference section for details about additional methods.
Best practices for initialization and usage
- We recommend initializing
KameleoonClient
as a singleton as early as possible after the application starts. This ensures that initialization begins promptly, as it may take some time. Since initialization is asynchronous, it does not block or delay the application's startup process. - Before using
KameleoonClient
, verify that it is initialized by calling therunWhenReady
method. Otherwise, attempts to use the client before it is ready will result in errors. - ⚠️ Most key methods may throw errors, so proper exception handling is required. Be sure to review the documentation for each method you use to understand its potential errors.
- Swift
- Swift (Async)
// Initialize `KameleoonClient` on application startup and use it as a singleton later
do {
let kameleoonClient = try KameleoonClientFactory.create(siteCode: "<siteCode>");
} catch {}
// Example: Apply a discount percentage based on an feature flag variable's value
func applyDiscountIfApplicable() {
client.runWhenReady(timeoutMilliseconds: 1000) { ready in
guard ready else { return }
if let variation = try? client.getVariation(featureKey: "discount"),
let discount = variation.variables["discount_value"]?.value as? Double {
applyDiscount(value: discount)
}
}
}
// Initialize `KameleoonClient` on application startup and use it as a singleton later
do {
let kameleoonClient = try KameleoonClientFactory.create(siteCode: "<siteCode>");
} catch {}
// Example: Apply a discount percentage based on an feature flag variable's value
func applyDiscountIfApplicable() async throws {
try await client.runWhenReady(timeoutMilliseconds: 1000)
if let variation = try client.getVariation(featureKey: "discount"),
let discount = variation.variables["discount_value"]?.value as? Double {
applyDiscount(value: discount)
}
}
Activating a feature flag
Retrieving a flag configuration
To implement a feature flag in your code, you must first create the feature flag in your Kameleoon account.
To determine the status or variation of a feature flag for a specific user, you should use the getVariation()
or isFeatureActive()
method to retrieve the configuration based on the featureKey
.
The getVariation()
method handles both simple feature flags with ON/OFF states and more complex flags with multiple variations. The method retrieves the appropriate variation for the user by checking the feature rules, assigning the variation, and returning it based on the featureKey
and visitorCode
.
The isFeatureActive()
method can be used if you want to retrieve the configuration of a simple feature flag that has only an ON or OFF state, as opposed to more complex feature flags with multiple variations or targeting options.
If your feature flag has associated variables (such as specific behaviors tied to each variation) getVariation()
also enables you to access the Variation
object, which provides details about the assigned variation and its associated experiment. This method checks whether the user is targeted, finds the visitor’s assigned variation, and saves it to storage. When track=true
, the SDK will send the exposure event to the specified experiment on the next tracking request, which is automatically triggered based on the SDK’s tracking_interval_millisecond
. By default, this interval is set to 1000 milliseconds (1 second).
The getVariation()
method allows you to control whether tracking is done. If track=false
, no exposure events will be sent by the SDK. This is useful if you prefer not to track data through the SDK and instead rely on client-side tracking managed by the Kameleoon engine, for example. Additionally, setting track=false
is helpful when using the getVariations()
method, where you might only need the variations for all flags without triggering any tracking events. If you want to know more about how tracking works, view this article
Adding data points to target a user or filter / breakdown visits in reports
To target a user, ensure you've added relevant data points to their profile before retrieving the feature variation or checking if the flag is active. Use the addData()
method to add these data points to the user's profile.
To retrieve data points that have been collected on other devices, use the getRemoteVisitorData()
method. This method asynchronously fetches data from our servers. However, it is important you call getRemoteVisitorData()
before retrieving the variation or checking if the feature flag is active, as this data might be required to assign a user to a given variation of a feature flag.
To learn more about available targeting conditions, read our detailed article on the subject.
Additionally, the data points you add to the visitor profile will be available when analyzing your experiments, allowing you to filter and break down your results by factors like device. See the complete list here.
If you need to track additional data points beyond what's automatically collected, you can use Kameleoon's Custom Data feature. Custom Data allows you to capture and analyze specific information relevant to your experiments. Don't forget to call the flush()
method to send the collected data to Kameleoon servers for analysis.
Tracking goal conversions
When a user completes a desired action (such as making a purchase), it is recorded as a conversion. To track conversions, use the trackConversion()
method and provide the required goalId
parameter.
The conversion tracking request will be sent along with the next scheduled tracking request, which the SDK sends at regular intervals (defined by tracking_interval_millisecond
). If you prefer to send the request immediately, use the flush()
method with the parameter instant=true
.
Cross-device experimentation
To support visitors who access your app from multiple devices, Kameleoon allows you to synchronize previously collected visitor data across each of the visitor's devices and reconcile their visit history across devices through cross-device experimentation. We recommend reading our article on cross-device experimentation for more information on how Kameleoon handles data across devices and detailed use cases.
Synchronizing custom data across devices
Although custom mapping synchronization is used to align visitor data across devices, it is not always necessary. Below are two scenarios where custom mapping sync is not required:
Same user ID across devices
If the same user ID is used consistently across all devices, synchronization is handled automatically without a custom mapping sync. It is enough to call the getRemoteVisitorData()
method when you want to sync the data collected between multiple devices.
Multi-server instances with consistent IDs
In complex setups involving multiple servers (for example, distributed server instances), where the same user ID is available across servers, synchronization between servers (with getRemoteVisitorData()
) is sufficient without additional custom mapping sync.
Customers who need additional data can refer to the getRemoteVisitorData()
method description for further guidance. In the below code, it is assumed that the same unique identifier (in this case, the visitorCode
, which can also be referred to as userId
) is used consistently between the two devices for accurate data retrieval.
If you want to sync collected data in real time, you need to choose the scope Visitor for your custom data.
- Swift
- Swift (Async)
// In this example, Custom data with index `90` was set to "Visitor" scope in Kameleoon.
let visitorScopeCustomDataIndex = 90
kameleoonClient.addData(CustomData(id: visitorScopeCustomDataIndex, values: "your data"))
kameleoonClient.flush()
// Before working with the data, call `getRemoteVisitorData`.
kameleoonClient.getRemoteVisitorData { result in
// After calling, the SDK on Device B will have access to CustomData of Visitor scope defined on Device A.
// So, "your data" will be available to target and track the visitor.
}
// In this example, Custom data with index `90` was set to "Visitor" scope in Kameleoon.
let visitorScopeCustomDataIndex = 90
kameleoonClient.addData(CustomData(id: visitorScopeCustomDataIndex, values: "your data"))
kameleoonClient.flush()
// Before working with the data, call `getRemoteVisitorData`.
try await kameleoonClient.getRemoteVisitorData()
// After calling, the SDK on Device B will have access to CustomData of Visitor scope defined on Device A.
// So, "your data" will be available to target and track the visitor.
Using custom data for session merging
Cross-device experimentation allows you to combine a visitor's history across each of their devices (history reconciliation). History reconciliation allows you to merge different visitor sessions into one. To reconcile visit history, you can use CustomData
to provide a unique identifier for the visitor. For more information, see our dedicated documentation.
After cross-device reconciliation is enabled, calling getRemoteVisitorData()
with the parameter userId
retrieves all known data for a given user.
Sessions with the same identifier will always be shown the same variation in an experiment. In the Visitor view of your experiment's results pages, these sessions will appear as a single visitor.
The SDK configuration ensures that associated sessions always see the same variation of the experiment. However, there are some limitations regarding cross-device variation allocation. We've outlined these limitations here.
Follow the activating cross-device history reconciliation guide to set up your custom data on the Kameleoon platform.
Afterwards, you can use the SDK normally. The following methods that may be helpful in the context of session merging:
getRemoteVisitorData()
with passedisUniqueIdentifier=true
toKameleoonClientConfig
- to retrieve data for all linked visitors.trackConversion()
orflush()
with passedisUniqueIdentifier=true
toKameleoonClientConfig
- to track some data for specific visitor that is associated with another visitor.
As the custom data you use as the identifier must be set to Visitor scope, you need to use cross-device custom data synchronization to retrieve the identifier with the getRemoteVisitorData()
method on each device.
Here's an example of how to use custom data for session merging.
- Swift
- Swift (Async)
// In this example, `91` represents the Custom Data's index,
// configured as a unique identifier in Kameleoon.
let mappingIndex = 91;
let featureKey = "ff123";
// 0. Initializing anonymous KameleoonClient
// Assume `anonymousVisitorCode` is the randomly generated ID for the visitor.
let anonymousKameleoonClient = KameleoonClientFactory.create(
siteCode: siteCode,
visitorCode: anonymousVisitorCode
)
anonymousKameleoonClient.runWhenReady { result in
// ...
}
// 1. Before the visitor is authenticated
// Retrieve the variation for an unauthenticated visitor.
let anonymousVariation = anonymousKameleoonClient.getVariation(featureKey)
// 2. After the visitor is authenticated
// Assume `userId` is the visitor code of the authenticated visitor.
anonymousKameleoonClient.addData(CustomData(id: mappingIndex, values: userId))
anonymousKameleoonClient.flush(instant: true)
KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
siteCode: siteCode,
visitorCode: userId,
config: KameleoonClientConfig(
isUniqueIdentifier: true // Indicate that `userId` is a unique identifier
)
)
userKameleoonClient.runWhenReady { result in
// ...
}
// 3. After the visitor has been authenticated
// Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
let userVariation = userKameleoonClient.getVariation(featureKey: featureKey)
let isSameVariation = userVariation.key == anonymousVariation.key // true
// The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
userKameleoonClient.trackConversion(goalId: 123, revenue: 10.0);
// Additionally, the linked visitors will share all fetched remote visitor data.
userKameleoonClient.getRemoteVisitorData { result in
// ...
}
// In this example, `91` represents the Custom Data's index,
// configured as a unique identifier in Kameleoon.
let mappingIndex = 91;
let featureKey = "ff123";
// 0. Initializing anonymous KameleoonClient
// Assume `anonymousVisitorCode` is the randomly generated ID for the visitor.
let anonymousKameleoonClient = KameleoonClientFactory.create(
siteCode: siteCode,
visitorCode: anonymousVisitorCode
)
try await anonymousKameleoonClient.runWhenReady()
// 1. Before the visitor is authenticated
// Retrieve the variation for an unauthenticated visitor.
let anonymousVariation = anonymousKameleoonClient.getVariation(featureKey)
// 2. After the visitor is authenticated
// Assume `userId` is the visitor code of the authenticated visitor.
anonymousKameleoonClient.addData(CustomData(id: mappingIndex, values: userId))
anonymousKameleoonClient.flush(instant: true)
KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
siteCode: siteCode,
visitorCode: userId,
config: KameleoonClientConfig(
isUniqueIdentifier: true // Indicate that `userId` is a unique identifier
)
)
try await userKameleoonClient.runWhenReady()
// 3. After the visitor has been authenticated
// Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
let userVariation = userKameleoonClient.getVariation(featureKey: featureKey)
let isSameVariation = userVariation.key == anonymousVariation.key // true
// The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
userKameleoonClient.trackConversion(goalId: 123, revenue: 10.0);
// Additionally, the linked visitors will share all fetched remote visitor data.
try await userKameleoonClient.getRemoteVisitorData()
In this example, we have an application with a login page. Since we don't know the user ID at the moment of login, we use an anonymous visitor automatically generated by SDK. Visitor code can be retrieved with getVisitorCode()
method. After the user logs in, we can associate the anonymous visitor with the user ID and use it as a unique identifier for the visitor.
Targeting conditions
The Kameleoon SDKs support a variety of predefined targeting conditions that you can use to target users in your campaigns. For the list of conditions this SDK supports, see use visit history to target users.
You can also use your own external data to target users.
Logging
The SDK generates logs to reflect various internal processes and issues.
Log levels
The SDK supports configuring limiting logging by a log level.
// The `none` log level does not allow logging.
KameleoonLogger.logLevel = .none
// The `ERROR` log level only allows logging issues that may affect the SDK's main behaviour.
KameleoonLogger.logLevel = .error
// The `WARNING` log level allows logging issues which may require additional attention.
// It extends the `ERROR` log level.
// The `WARNING` log level is a default log level.
KameleoonLogger.logLevel = .warning
// The `INFO` log level allows logging general information on the SDK's internal processes.
// It extends the `WARNING` log level.
KameleoonLogger.logLevel = .info
// The `DEBUG` log level allows logging extra information on the SDK's internal processes.
// It extends the `INFO` log level.
KameleoonLogger.logLevel = .debug
Custom handling of logs
The SDK writes its logs to the console output by default. This behaviour can be overridden.
Logging limiting by a log level is performed apart from the log handling logic.
public struct CustomLogger: Logging {
let customLogger = Logger(subsystem: "com.yourcompany.app", category: "app")
public func log(level: LogLevel, message: String) {
switch level {
case .error:
customLogger.error("\(message)")
case .warning:
customLogger.warning("\(message)")
case .info:
customLogger.info("\(message)")
case .debug:
customLogger.debug("\(message)")
default:
break
}
}
}
// Log level filtering is applied separately from log handling logic.
// The custom logger will only accept logs that meet or exceed the specified log level.
// Ensure the log level is set correctly.
KameleoonLogger.logLevel = .debug // Optional, defaults to `LogLevel.WARNING`.
KameleoonLogger.logger = CustomLogger()
Apple privacy compliance
Starting May 1st, 2024, Apple requires apps that include a third-party SDK, such as the Kameleoon iOS SDK, to have a privacy manifest file for that SDK. The latest version of the SDK is code-signed, compliant, and includes a valid manifest file with the SDK. No action is required if you're using the Kameleoon iOS SDK version 4.2 or later.
Reference
This is the full reference documentation for the Kameleoon iOS (Swift) SDK.
Initialization
Once you have installed the SDK in your application, the first step is to initialize Kameleoon. All of your application's interactions with the SDK, such as triggering an experiment, are accomplished using this Kameleoon client object.
create()
Call this method before any others to initialize the SDK. This method is in KameleoonClientFactory
. This creates an instance of KameleoonClient
to manage all interactions between the SDK and your app.
You can customize the behavior of the SDK (for example, the environment, the credentials, and so on) by providing a configuration object. Otherwise, the SDK tries to find your configuration file and uses it instead.
let visitorCode = "visitorCode"
let siteCode = "a8st4f59bj"
do {
// pass client configuration as an argument
let config = try KameleoonClientConfig(
clientId: "clientId", // optional
clientSecret: "clientSecret", // optional
refreshIntervalMinute: 15, // optional, 60 minutes by default
dataExpirationIntervalMinute: 60*24*365, // optional, `Data.distantFuture` by default
defaultTimeoutMillisecond: 10_000, // optional, 10_000 milliseconds by default
trackingIntervalMillisecond: 500, // optional, 1000 milliseconds by default
environment: "production", // optional
isUniqueIdentifier: true, // optional, false by default
)
let kameleoonClient = try KameleoonClientFactory.create(
sitecode: siteCode,
visitorCode: visitorCode, // optional
config: config // optional
)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
// Indicates that provided site code is empty
} catch {
// Unexpected error occurred
}
do {
// read client configuration from a file 'kameleoon-client-swift.plist'
// visitor code isn't provided, so SDK generates a random visitor code which will be used in the future
let kameleoonClient = KameleoonClientFactory.create(siteCode: siteCode)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
// Indicates that provided site code is empty
} catch {
// Unexpected error occurred
}
ready
For mobile SDKs, the initialization of the Kameleoon Client is not immediate. The SDK needs to perform a server call to retrieve the current configuration for all active experiments. Check if the SDK is ready by calling this method before triggering an experiment. Alternatively, you can use the runWhenReady()
method with a callback.
let ready = kameleoonClient.ready
Return value
Name | Type | Description |
---|---|---|
ready | Bool | Boolean representing the status of the SDK (true if fully initialized, false if not ready to be used). |
runWhenReady()
- 🔄 Performs an asynchronous request (if the configuration is outdated or missing)
For mobile SDKs, the KameleoonClient
cannot initialize immediately, as it needs to perform a server call to retrieve the current configuration for all feature flags. Use the runWhenReady()
method to wait until the client is ready for use. Additionally, you can set a maximum timeout period to control how long the client will wait before it becomes ready.
If ready=true
, the KameleoonClient
is fully initialized, and feature flags will be evaluated and assigned their respective variations. If the result is false
or a timeout occurs, the initialization will not complete.
The callback or asynchronous code should handle applying the reference variation, as a timeout will exclude the user from the feature flag.
Since the initial configuration may require a server call, this mechanism is asynchronous. Therefore, you should either:
- Provide a
completion
callback as an argument to the method to ensure you are notified when theKameleoonClient
is fully initialized and ready for use. - Use asynchronous operations.
- Swift
- Swift (Async)
func applyRecommendedProductsVariation() {
let defaultValue = 5 // Default control number for recommended products
kameleoonClient.runWhenReady(timeoutMilliseconds: 1000) { ready in
guard ready else {
applyVariation(recommendedProductsNumber: defaultValue)
return
}
let variation = try? kameleoonClient.getVariation(featureKey: "featureKey")
let recommendedProductsNumber = variation.variables["recommendedProductsNumber"]?.value as? Int ?? defaultValue
applyVariation(recommendedProductsNumber: recommendedProductsNumber)
}
}
Arguments
Name | Type | Description | Default |
---|---|---|---|
timeoutMilliseconds (optional) | Int | Timeout for the initialization process | defaultTimeoutMillisecond or default_timeout_millisecond |
callback (required) | (Bool) -> Void | Callback object. It is a lambda expression that will get a Bool argument representing whether the KameleoonClient became ready before the timeout was reached. |
A common mistake is calling async
functions with try?
or inside a nested do-catch
block without rethrowing CancellationError
. This can interfere with task cancellation, causing unexpected behavior.
To ensure correct task cancellation, avoid using try?
or do-catch
around async
functions unless you explicitly rethrow CancellationError
.
func applyRecommendedProductsVariation() async throws {
let defaultValue = 5 // Default control number for recommended products
try await kameleoonClient.runWhenReady(timeoutMilliseconds: 1000)
let variation = try kameleoonClient.getVariation(featureKey: "featureKey")
let recommendedProductsNumber = variation.variables["recommendedProductsNumber"]?.value as? Int ?? defaultValue
applyVariation(recommendedProductsNumber: recommendedProductsNumber)
}
Arguments
Name | Type | Description | Default |
---|---|---|---|
timeoutMilliseconds (optional) | Int | Timeout for the initialization process | defaultTimeoutMillisecond or default_timeout_millisecond |
Errors thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Exception indicating that the SDK is not fully initialized yet. |