iOS SDK 4.x to 5.0 migration guide
Read time: 9 minutes
Last edited: Aug 16, 2024
Overview
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:
Platform | 4.x Target | 5.x Target |
---|---|---|
iOS | 8.0 | 10.0 |
watchOS | 2.0 | 3.0 |
tvOS | 9.0 | 10.0 |
macOS | 10.10 | 10.12 |
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 Get 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 LDFlagChangeHandler
s or LDFlagCollectionChangeHandler
s 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:
LDClient.shared.stop()
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 toArray
.==
and!=
extension toOptional<[String: Any]>
(note that this was not declared asEquatable
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 withLDConfig.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 Get started section of the iOS reference guide.
- When shutting down the client instance by calling
close
(formerlystop
), 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.