Migrating to version 11#
This guide helps you migrate from Storyteller SDK version 10.x.x to 11.0.x. Version 11.0.x introduces several breaking changes that improve the SDK's architecture and consistency. Version 11 focuses on three major architectural improvements:
- Shared Instance Pattern - Static methods replaced with
Storyteller.shared - Consistent Naming - Public types now use
Storytellerprefix - Modern Swift Concurrency - Callback-based APIs replaced with async/await
Storyteller shared instance#
The Storyteller class has moved from using static methods to a shared instance pattern. All API calls must now use Storyteller.shared instead of calling static methods directly on the class.
Usage example#
// Before (10.x.x):
Storyteller.delegate = myDelegate
// After (11.x.x):
Storyteller.shared.delegate = myDelegate
See the shared instance pattern in the Showcase app where Storyteller.shared.modules, Storyteller.shared.theme, and Storyteller.shared.delegate are configured in AppDelegate.setupStoryteller.
Storyteller Prefix for Public Types#
All public types now start with the Storyteller prefix for better namespace consistency and to avoid naming conflicts with your app code.
Type Renames#
| Old Name | New Name |
|---|---|
UserInput |
StorytellerUserInput |
ClipCollectionConfiguration |
StorytellerClipCollectionConfiguration |
Placement |
StorytellerPlacement |
Category |
StorytellerCategory |
CategoryDetail |
StorytellerCategoryDetail |
CurrentCategoryData |
StorytellerCurrentCategoryData |
UserActivity |
StorytellerUserActivity |
UserActivityData |
StorytellerUserActivityData |
CodableIgnored |
StorytellerCodableIgnored |
Alignment |
StorytellerAlignment |
FontProvider |
StorytellerFontProvider |
TextCasing |
StorytellerTextCasing |
PlayerIcons |
StorytellerPlayerIcons |
InstructionIcons |
StorytellerInstructionIcons |
Async/Await functions#
All callback-based APIs have been replaced with modern Swift async/await patterns. The following Storyteller.shared methods are now async functions:
initialize(apiKey:userInput:eventTrackingOptions:)dismissPlayer(animated:dismissReason:)openDeepLink(url:)openStory(id:openReason:)openStory(externalId:openReason:)openPage(id:openReason:)openCategory(category:openReason:)openCollection(configuration:openReason:)openClipByExternalId(collectionId:externalId:openReason:)openSheet(id:)getStoriesCount(for:)getClipsCount(for:)openSearch()
Migration Examples#
// Before (10.x.x):
Storyteller.initialize(
apiKey: "your-api-key",
onComplete: {
print("SDK initialized successfully")
},
onError: { error in
print("Initialization failed: \(error)")
}
)
// After (11.x.x):
Task {
do {
try await Storyteller.shared.initialize(apiKey: "your-api-key")
print("SDK initialized successfully")
} catch {
print("Initialization failed: \(error)")
}
}
See the Showcase initialization flow using async/await in StorytellerService.setup.
Additional Breaking Changes#
Event Tracking Options#
eventTrackingOptions can now only be set during SDK initialization:
Before (10.x.x):
// Initialize SDK
Storyteller.initialize(
apiKey: "your-api-key",
onComplete: {
print("SDK initialized successfully")
},
onError: { error in
print("Initialization failed: \(error)")
}
)
// Later in the code, modify tracking options
Storyteller.eventTrackingOptions = StorytellerEventTrackingOptions(
enablePersonalization: true,
enableStorytellerTracking: true,
enableUserActivityTracking: true,
enableAdTracking: true,
enableFullVideoAnalytics: true,
enableRemoteViewingStore: true,
disabledFunctionalFeatures: []
)
After (11.x.x):
// Set tracking options during initialization
let trackingOptions = StorytellerEventTrackingOptions(
enablePersonalization: true,
enableStorytellerTracking: true,
enableUserActivityTracking: true,
enableAdTracking: true,
enableFullVideoAnalytics: true,
enableRemoteViewingStore: true,
disabledFunctionalFeatures: []
)
let userInput = StorytellerUserInput(externalId: "user-id")
Task {
try await Storyteller.shared.initialize(
apiKey: "your-api-key",
userInput: userInput,
eventTrackingOptions: trackingOptions
)
}
See how the Showcase app builds StorytellerEventTrackingOptions and passes them during initialization in StorytellerService.setup.
To change tracking options after initialization, you must reinitialize the SDK. See Privacy and Tracking for more information.
SwiftUI Grids#
The isScrollable parameter no longer has a default value and must be explicitly provided:
// Before (10.x.x):
// isScrollable defaulted to false
StorytellerStoriesGrid(model: storiesModel)
StorytellerClipsGrid(model: clipsModel)
// After (11.x.x):
// isScrollable must be explicitly provided
StorytellerStoriesGrid(isScrollable: false, model: storiesModel)
StorytellerClipsGrid(isScrollable: false, model: clipsModel)
See the Showcase SwiftUI grid usage in StoriesListView.
StorytellerListViewDelegate#
The onTileTapped method now provides richer context via the StorytellerTileType enum:
// Before (10.x.x):
extension MyViewController: StorytellerListViewDelegate {
func onTileTapped(id: String) {
print("Tapped tile with ID: \(id)")
}
}
// After (11.x.x):
extension MyViewController: StorytellerListViewDelegate {
func onTileTapped(type: StorytellerTileType) {
switch type {
case .clip(let clipId, let collectionId, let categories):
print("Tapped clip: \(clipId) in collection: \(collectionId), categories: \(categories)")
case .story(let storyId, let categories):
print("Tapped story: \(storyId), categories: \(categories)")
}
}
}
See the Showcase onTileTapped flow (including categories) in StorytellerItemView.listAction.
Other breaking changes#
The following theme properties have been removed and are now configured in the CMS:
tiles.title.show- configured in CMSengagement.poll.showVoteCount- configured in CMS
Need Help#
If you encounter any issues during the migration:
- Check the Changelog for a detailed version history
- Don't hesitate to reach out if you continue to face difficulties