• Home
  • Integrations
  • SDKs
  • Guides
  • API docs
No results for ""


iOS SDK 4.x to 5.0 migration guide

Read time: 9 minutes
Last edited: Apr 29, 2023


This topic explains how to adapt code that currently uses a 4.x version of the iOS client-side SDK to use version 5.0 or later.

Sections in this topic address different changes and updates between versions 4.x and 5.0 of the SDK.

Deployment target changes

The minimum platform targets have changed. Here are the targets:

Platform4.x Target5.x Target

Build considerations

The SDK has replaced the internal dependency on the Objective-C eventsource implementation DarklyEventSource with a pure Swift implementation LDSwiftEventSource. For most methods of integrating the SDK as a dependency of your application this should require no manual intervention. Methods of integrating the SDK that require explicitly referencing the framework products may require manual intervention, some cases of which are:

  • Manually integrating the SDK project as a subproject of your application project.
  • Using Carthage without a copy-frameworks build phase.
  • Otherwise manually including the built frameworks for the SDK and its dependencies.

For these cases the DarklyEventSource framework products should be removed from your project configuration. The new dependency LDSwiftEventSource does not require being manually specified as a dependency when being built as a subproject of your application, but may require being manually included when manually copying built frameworks.

Initializing the SDK and the shared LDClient instance

In 4.x versions of the iOS SDK a single shared LDClient instance was exposed by the static LDClient.shared property. This instance was initially unstarted, and configured with a default LDConfig and LDUser. It would then be reconfigured and started by the application by calling start or startCompleteWhenFlagsReceived on the shared instance.

In the 5.0 release of the iOS SDK, the LDClient.shared property was removed, and start is now a static method of the LDClient class. To initialize the shared instance(s), start is called with the desired SDK configuration and optionally a LDUser. After start returns, it is safe to retrieve the primary instance with the new LDClient.get() static method, or a secondary environment with the LDClient.getForMobileKey() static method.

Here is an an example of the start method:

let config = LDConfig(mobileKey: "mobile-key-123abc")
let user = LDUser(key: "user-key-123abc")
LDClient.shared.start(config: config, user: user)

If your application was already taking advantage of the startCompleteWhenFlagsReceived method to determine when flags are received for the configured user, the static start method also supports the startWaitSeconds and completion parameters that follow the same behavior that startCompleteWhenFlagReceived had. More information on the behavior of start is available in the getting started section of the main iOS SDK reference.

Reconfiguring the SDK

The setter for the LDClient.config property was removed in the 5.0 release. You should specify your configuration up front when initializing the SDK with start. After the client initializes, reconfiguration is restricted to using instance methods such as setOnline to change the SDK state.

Updating the active user context

The iOS SDK always operates in the context of a specific user. The SDK supports changing this user in cases that the human user logs in or out of the host application, for example.

In 4.x versions of the iOS SDK the active user could be changed by setting the user property of the shared LDClient instance. In version 4.2.0 of the SDK, this setter was deprecated in favor of the identify(user: completion:) method which has an optional completion indicating when flags have been received for the new user context.

In the 5.0 release, the setter for the user property has been removed. If your application had already migrated to identify, additional changes are not required as the behavior has not changed. If your application still uses the user property to update the active user context, you need to migrate to the identify method.

Here is an example of migrating to the identify method:

let newUser = LDUser(key: "user-key-123abc")
LDClient.shared.user = newUser

One other change to be aware of is that the optional LDUser initializer, LDUser.init?(object: ), as been removed in preference of using LDUser.init(userDictionary: ) directly.

Read more about changing the user context.

Evaluating flags

Due to a change of the parameter naming, all variation calls that specify the fallback parameter will need to be updated to use the defaultValue parameter name instead. This renaming was introduced to distinguish these application default values from the fallback values specified in the flag configuration done in the flags list.

Here is an an example using the new parameter name:

let flagValue = LDClient.shared.variation(forKey: "flag-key-123abc", fallback: false)

If your application uses the variationDetail methods, and referenced the name of the return type directly, it must also be updated for the renaming of that type.

For Swift, the type has been renamed from EvaluationDetail to LDEvaluationDetail to keep with the prefixed naming convention the rest of the SDK API uses.

In the Objective-C interface the returned type is not generic, so there is a separate class for each type. In 5.0 these have Objective-C names specified to be LD<T>EvaluationDetail where <T> is the type of the flag value, rather than the Swift implementation class names which were following the pattern ObjC<T>EvaluationDetail. If you were using the binding classes in a Swift context they were also renamed from ObjC<T>EvaluationDetail to Objc<T>EvaluationDetail to match the capitalization of other Objective-C wrapper classes.

Here is an example using the new naming method:

let flagValueDetail: EvaluationDetail<Bool> = LDClient.shared.variationDetail(forKey: "flag-key-123abc", fallback: false)

Additionally, the deprecated variationAndSource methods have been removed in the 5.0 release. If your application was making use of these methods, upgrading to the 5.0 release will require migrating to the variationDetail methods.

Also related to flag evaluation, the allFlagValues method has been renamed to allFlags for consistency with other SDKs. If your application used allFlagValues the references must be changed to allFlags.

Realtime updates

The SDK supports registering observers on flags to be notified when the flag value has changed. While the process for registering a receiver has not changed in the 5.0 release, the properties on the change notification value passed to your observer have changed.

For Swift, the properties LDChangedFlag.oldValueSource and LDChangedFlag.newValueSource were removed. Any LDFlagChangeHandlers or LDFlagCollectionChangeHandlers can no longer use these properties on on the provided LDChangedFlag(s).

The Objective-C bindings similarly no longer include the oldValueSource and newValueSource properties. Additionally, the static properties nilSource and typeMismatch of the LDChangedFlag Objective-C binding have been removed. As handlers can be registered for a specific flag value type, LDChangedFlag.typeMismatch was provided to allow using the value source to detect when a flag observer had been called for an value update with a non-matching type. In order to still allow handling this case, the LD<T>ChangedFlag classes now expose the boolean typeMismatch property that indicates whether this situation has occurred.

Recording custom events

If your application uses trackEvent to record custom events, it is necessary to rename usages to track. Additionally, the type of Error that track throws when the given data parameter is not JSON convertible has been changed from JSONSerialization.JSONError.invalidJsonObject to LDInvalidArgumentError.

Here is an example using the new names:

do {
try LDClient.shared.trackEvent(key: "key", data: ["abc": 123])
} catch JSONSerialization.JSONError.invalidJsonObject {
// Do something with the error
} catch {}

To avoid polluting classes external to the SDK, JSONSerialization.JSONError has been removed.

Additionally, LDClient.reportEvents() has been renamed to LDClient.flush(). If your application was using reportEvents to send events to LaunchDarkly immediately, this usage will need to be updated to flush.

Shutting down the SDK

Under normal use it is not necessary to explicitly shut down the SDK. If your application was previously shutting down the SDK with LDClient.stop(), this method has been renamed to LDClient.close() for consistency with other SDKs.

To shut down the SDK:


Removing exposed implementation details

The following were removed from the publicly exposed surface of the SDK. These were implementation details that were not intended to be public:

  • isEqual extension to Array.
  • == and != extension to Optional<[String: Any]> (note that this was not declared as Equatable conformance).
  • Sysctl struct.

Highlights of new functionality

The 5.0 release also includes new features and improvements as described in the release notes.

These include:

  • The SDK now has support for multiple LDClient instances that are tied to separate mobile keys, allowing the evaluation of flags in multiple environments. For more information on this feature, read Multiple environments.
  • The SDK now periodically sends diagnostic data to LaunchDarkly, describing the version and configuration of the SDK, properties of the underlying operating system, and performance statistics. No credentials or identifiable values are included. This behavior can be disabled with LDConfig.diagnosticOptOut(Bool) or configured with LDConfig.diagnosticRecordingInterval(TimeInterval).
  • The LaunchDarkly iOS SDK is now compatible with the Swift Package Manager. Read more about building with the Swift Package Manager in the Getting started section of the iOS reference guide.
  • When shutting down the client instance by calling close (formerly stop), the event queue is flushed prior to shutting down. This ensures that all pending events are submitted before the client connections are closed.
  • The SDK configuration now offers the ability to set a wrapper name (LDConfig.wrapperName) and version (LDConfig.wrapperVersion). These allow a library wrapping the SDK (for example, the React Native SDK) to identify itself for usage data.