Skip to content

12.0.0

Choose a tag to compare

@tklucher tklucher released this 21 Apr 20:31
· 19 commits to develop since this release
dd4ec13

12.0.0 Migration Guide

Built on Xcode 16.2.0
Min deployment target iOS 15.6
In order to better position the codebase for the transition to Swift 6 and other future iPhone advancements, we have made a few changes to the startup of the SDK. These changes now stage the startup of the CirrusMD SDK, preventing excess memory from being allocated early on in the process, speeding up app startup for all SDK customers as well as lowering the memory footprint of the SDK until the UI is shown to a user .

We have split the startup of the SDK into 3 steps.

Step 1 Memory creation:

A new function called startSDK(withLaunchOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) will replace configuration as the function to call at launch of your App. This allows you to delay configuration of the SDK until your app is fully loaded. Also, you can now configure the SDK any time between when this startup is called in the App delegate and the tokens are set to log in the user. This starts the base memory structure of the SDK and allows the delegate functions to work properly for notifications.

Old Code:

let config = CirrusMDConfig()
config.logLevel = .verbose
config.primaryColor = UIColor.black
config.primaryColorDarkMode = UIColor.purple
config.title = "Your Custom Title"
config.launchOptions = launchOptions
config.enableSettings = true
CirrusMD.singleton.config = config

New Code

CirrusMD.singleton.startSDK(withLaunchOptions: launchOptions)

Step 2 Configure the SDK:

Very little has changed with the configuration object itself. First, as you read above, we removed launchOptions from the configuration. This means that you can now configure the SDK any time after starting your app. This allows you to better control SDK memory management and allocation. Setting Configure will set up the style code that all CirrusMD UI uses for its design. The UI itself is not spun up, so this is still a really low memory impact and if you would like to make the smallest change possible while testing this new release, you can make this call right after the startSDK with no issues.
The main change made to the CirrusMDConfig is how it is set. The order of operations to start the SDK has not changed and is simplified in the number of steps. However, we now enforce the startup order in code. As a result, the new CirrusMD.singleton.setSDKConfiguration(config) function now has a discardable result that you can check to see if the configuration is set properly. It can return .success or .sdkAlreadyConfiguredMustCallLogout which is returned if the SDK has already been configured with a user. Calling logout will log out the current patient and allow for the setting of a new configuration. Once you log in with a user, the configuration cannot be changed. The reason for this is simple: once a user is logged in we start getting the user’s data and UI ready and since this configuration changes UI it would cause UI issues. That is also why we made the result discardable as this will always succeed as long as it is called before CirrusMD.singleton.configureWithToken(token, andSecret: secret)

Old Code:

let config = CirrusMDConfig()
config.logLevel = .verbose
config.primaryColor = UIColor.black
config.primaryColorDarkMode = UIColor.purple
config.title = "Your Custom Title"
config.launchOptions = launchOptions
config.enableSettings = true
CirrusMD.singleton.config = config

New Code

let config = CirrusMDConfig()
config.logLevel = .verbose
config.primaryColor = UIColor.black
config.primaryColorDarkMode = UIColor.purple
config.title = "Your Custom Title"
config.launchOptions = launchOptions
config.enableSettings = true
CirrusMD.singleton.setSDKConfiguration(config)

Optional:

let result = CirrusMD.singleton.setSDKConfiguration(config)
switch result {
  case .success:
    print("Successfully set SDK Configuration.")
  case .sdkAlreadyConfiguredMustCallLogout:
    print("SDK ERROR: Patient has already been configured, must call logout first.")
  @unknown default:
    print("SDK ERROR: Unknown. \(result.rawValue)")
}

Step 3 Configure the SDK with a Patient:

This is where we reduced some complexity. In the old configuration, you needed to set the secret and then set the token in different steps. We also required that they be called in that order or the set token call would fail. We have removed this complexity and now have a single function call that takes in both the authentication token and the secret, then verifies them, and attempts to log in the user with those credentials. This is the point where the SDK is fully working and the UI can be shown to the user, when the configuration is successful. If you run into any problem with the configureWithToken function and do not receive a success result, you can simply call the logout function on the SDK to reset it back to when you set the configuration in step 2 and then try again by calling CirrusMD.singleton.configureWithToken(token, andSecret: secret) after the logout.

Old Code:

CirrusMD.singleton.setSecret(secret)
/*
 Loads an SSO user from the provided token.`CirrusMDSDK.singleton.setSecret`
 must be called prior to calling `CirrusMDSDK.singleton.setToken`
*/
CirrusMD.singleton.setToken(token) { [weak self] (result) in
  switch result {
    case .success:
      NSLog("Set Token Success")
    case .invalidToken:
      NSLog("Set Token Invalid Token Error")
    case .noSecretProvided:
      NSLog("Set Token No Secret Provided")
    case .serviceUnavailable:
      NSLog("Set Token Service Unavailable")
    @unknown default:
      NSLog("Set Token Invalid Token Error")
  }
}

New Code

CirrusMD.singleton.configureWithToken(token, andSecret: secret) { (result) in
  switch result {
  case .success:
    print("Successfully set SDK Configuration.")
  case .invalidToken:
    print("SDK ERROR: Invalid SDK token.")
  case .noSecretProvided:
    print("Set Token No Secret Provided")
  case .sdkAlreadyConfiguredMustCallLogout:
    print("SDK ERROR: Patient has already been configured, must call logout first.")
  case .serviceUnavailable:
    print("Set Token Service Unavailable")
  @unknown default:
    print("SDK ERROR: Unknown. \(result.rawValue)")
  }
}

The last step is to implement any of the delegate methods for the CirrusMDDelegate that you have not already implemented. The Swift protocol now requires that all delegate methods be implemented if they are used or not. You can find an example of this in the Example code as part of this repository.

Should you run into any issues, please do not hesitate to reach out and we will provide you with any further information that will help you migrate the SDK code to the new format. All these changes are pretty minor and result in a faster startup and lower memory overhead for all SDK users while also giving you more control over the SDK startup process.

Known Issue: We are currently tracking a single known issue dealing with Core Graphics in iOS 18. This issue shows in the console logs and manifests as a small delay on the first tap in the SDK only while running on the simulator. We are currently not seeing the delay on any device we have tested however the Core Graphics warnings will still show in the console. The delay is minor, under 2 seconds and does not affect further use of the SDK and as stated above is not happening on device. We are committed to the best testing and customer experience so we have a developer working on this simulator issue and hope to have a resolution by the next release. We apologize for any inconveniences while testing.