iOS SDK: Migrating from v3 to v4
Version 4.0.0 is a full rewrite of the Castle iOS SDK in Swift, replacing the previous Objective-C implementation. This guide covers all breaking changes and how to update your integration.
Requirements
- iOS 13+ v4 drops support for iOS versions below 13.
Breaking changes
1.Import name
// v3
import Castle
// v4
import CastleSDK// v3
#import <Castle/Castle.h>
// v4
@import CastleSDK;2.Configuration
Castle.configureAsyncis new function, for better async support- The
Castle.configureandCastle.configureAsynccall can now throwCastleConfigurationErrorexceptions when the publishable key is invalid,configureis not called from the main thread or other settings are invalid. configure(sync version) is required to be called from the main thread, due to internal information collection, UIKit and other internal libraries require, as defined per Apple, to be run from main thread.
// v3
Castle.configure(publishableKey: "{Publishable-API-Key}")
// v4
let configuration = CastleConfiguration(publishableKey: "{Publishable-API-Key}")
// configure is a sync call required to run from main thread
try! Castle.configure(configuration)
// configureAsync is dispatched async to the main thread
do {
try await Castle.configureAsync(configuration)
NSLog("Castle configure successful")
// setup userJWT
// createRequestToken
} catch {
NSLog("Castle configure failed: \(error)")
}// v3
[Castle configureWithPublishableKey:@"{Publishable-API-Key}"];
// v4
CastleConfiguration *configuration = [[CastleConfiguration alloc] initWithPublishableKey:@"{Publishable-API-Key}"];
// configure is a sync call required to run from main thread
NSError *error = nil;
[Castle configure:configuration error:&error];
// configureAsync is dispatched async to the main thread
[Castle configureAsync:configuration completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"Castle configure failed: %@", error);
} else {
NSLog(@"Castle configure successful");
// setup userJWT
// createRequestToken
}
}];3.Request Token Creation
The createRequestToken method doesn't accept any options and generates tokens synchronously. Tokens can be created from any thread, they have no main thread requirement due to internal cache and observer architecture.
It is strongly advised to not create a token directly after configure , to give the SDK time to collect sensor data.
Furthermore if tokens are requested without the SDK being initialized the returned token will be nil.
// v3
let token: String = Castle.createRequestToken() // "" if not configured
// v4
let token: String? = Castle.createRequestToken() // nil if not configured// v3
NSString *token = [Castle createRequestToken]; // @"" if not configured
// v4
NSString *token = [Castle createRequestToken]; // nil if not configuredComplete Integration Sample
import CastleSDK
// sync version
let configuration = CastleConfiguration(publishableKey: "{Publishable-API-Key}")
configuration.isDebugLoggingEnabled = true
do {
try Castle.configure(configuration)
// Castle is ready - set user identity and track events
// if available, otherwise set at user login
Castle.userJwt("user-jwt-token")
Castle.screen(name: "App Started")
} catch {
NSLog("Castle configure failed: \(error)")
}
// async version
func setupCastle() async {
let configuration = CastleConfiguration(publishableKey: "{Publishable-API-Key}")
configuration.isDebugLoggingEnabled = true
do {
try await Castle.configureAsync(configuration)
// Castle is ready - set user identity and track events
// if available, otherwise set at user login
Castle.userJwt("user-jwt-token")
Castle.screen(name: "App Started")
} catch {
print("Castle configuration failed: \(error)")
}
}
// recommended usage form didFinishLaunching
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Task.detached {
await setupCastle()
}
return true
}@import CastleSDK;
// sync version
CastleConfiguration *configuration = [[CastleConfiguration alloc] initWithPublishableKey:@"{Publishable-API-Key}"];
configuration.debugLoggingEnabled = YES;
NSError *error = nil;
if ([Castle configure:configuration error:&error]) {
// Castle is ready - set user identity and track events
// if available, otherwise set at user login
[Castle setUserJwt:@"user-jwt-token"];
[Castle screenWithName:@"App Started"];
} else {
NSLog(@"Castle configure failed: %@", error);
}
// async version
- (void)setupCastle {
CastleConfiguration *configuration = [[CastleConfiguration alloc] initWithPublishableKey:@"{Publishable-API-Key}"];
configuration.debugLoggingEnabled = YES;
[Castle configureAsync:configuration completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"Castle configuration failed: %@", error);
} else {
// Castle is ready - set user identity and track events
// if available, otherwise set at user login
[Castle setUserJwt:@"user-jwt-token"];
[Castle screenWithName:@"App Started"];
}
}];
}
// recommended usage from didFinishLaunching
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions {
[self setupCastle];
return YES;
}Updated about 2 hours ago