Embedded Clips#
For the cases when you want to embed the Clips player inside your own view hierarchy, we provide the StorytellerClipsViewController.
Adding it in the UI#
The most common use case is to place it inside a UITabBarController:
let embeddedClipsVC = StorytellerClipsViewController()
let tabBarVC = UITabBarController()
tabBarVC.setViewControllers([embeddedClipsVC, someOtherVC], animated: false)
Or, if you wish to add it to your custom view hierarchy:
// somewhere inside a view controller
let embeddedClipsVC = StorytellerClipsViewController()
addChild(embeddedClipsVC)
view.addSubView(embeddedClipsVC.view)
// layout the view
embeddedClipsVC.didMove(toParent: self)
StorytellerClipsViewController has following public properties
topLevelBackButtonEnabled- whether the back button should be displayed when the player is at the top level of the collection. Defaults tofalse.canGoBack- whether the back button action is managed by the SDK. Whenfalse, the integrating app can handle the back button action. Whentrue, the SDK will manage the action by popping the top level category.delegate- delegate responsible for relaying events from theStorytellerClipsViewController.
Loading Clips#
In order for the View Controller to (re)load the clips, call configure(with configuration: StorytellerClipCollectionConfiguration) method.
StorytellerClipCollectionConfiguration struct has following properties:
collectionId- the id of the collection to be displayed.destination- specify whichcliporcategoryto show when opening the collection. Ifcliporcategoryis not specified or wrong value is set, we default to the first clip.theme- This property defines the overall appearance of the StorytellerClipsViewController. If this property is not specified, the global theme will be applied by default.openReason- Action type used for analytics to track why the collection was opened. If nil, the open reason is handled internally.context- Optional context data that will be included in analytics callbacks for attribution.
let configuration = StorytellerClipCollectionConfiguration(collectionId: "top-plays")
embeddedClipsVC.configure(with: configuration)
- possible values for
StorytellerClipCollectionConfiguration.Destinationare listed below:
public enum Destination {
case category(id: String)
case clip(id: String)
}
Note, configure(with configuration: StorytellerClipCollectionConfiguration) method does not reload the data if configuration.collectionId or configuration.destination weren't changed. Use reloadData() for that instead.
Auto-pause#
Besides for when the user pauses the Clips player, the SDK automatically pauses/plays based on visibility changes (e.g., when backgrounding/foregrounding the app, or when switching tabs in a UITabBarController). If you have a scenario which isn't covered (like displaying a modal or alert over the player), you can hint to the SDK using these methods:
embeddedClipsVC.willHide()- Call this before the player becomes obscured or inactive.embeddedClipsVC.willShow()- Call this when the player becomes visible or active again.
Note: Auto-pausing respects the user's explicit pause state. If the user manually paused, willShow() will not automatically resume playback.
ReloadData#
If you want to reload the data, you can call embeddedClipsVC.reloadData(). This will trigger a new request to the server, and will also reset the player to its initial state.
Note: If category filters are currently applied when reloadData() is called, the player will navigate back one level in the category stack instead of reloading the entire collection. If no category filters are applied, it reloads the top-level collection data.
Delegate#
If you want to customize the behaviour or observe events from the StorytellerClipsViewController, you can create a delegate conforming to StorytellerClipsDelegate and implement the following functions:
func onDataLoadStarted()- Called when data loading begins. Use it to show loading indicators.func onDataLoadComplete(success: Bool, error: Error?, dataCount: Int)- Called when data loading finishes (successfully or with an error).dataCountindicates the number of clips loaded.func topLevelBackTapped()- Called when the user taps the back button (if enabled viatopLevelBackButtonEnabled) while at the top level of the collection. The default implementation attempts to pop the view controller from the nearest navigation controller. Implement this for custom back navigation behavior.
Safe Area / Inset Management#
StorytellerClipsViewController relies on standard iOS Auto Layout and Safe Area Layout Guides. Ensure the view controller's view is constrained correctly within its parent, respecting the safe area, to prevent UI elements from being obscured by system bars (navigation bar, status bar, tab bar).
SwiftUI#
To implement the Clips player in SwiftUI, you can use the StorytellerClipsView wrapper.
It is configured by StorytellerClipsModel model, which has the following properties:
public var configuration: StorytellerClipCollectionConfiguration
public var topLevelBackButtonEnabled: Bool
public var canGoBack: Bool
public init(configuration: StorytellerClipCollectionConfiguration, topLevelBackButtonEnabled: Bool = false)
public func reloadData()
public func willShow()
public func willHide()
public func goBack()
where the configuration is the only required property.
configuration- configuration of the collection to be displayedtopLevelBackButtonEnabled- whether the back button should be displayed when the player is at the top level of the collection. Defaults tofalse.canGoBack- whether the back button action is managed by the SDK. Whenfalse, the integrating app can handle the back button action. Whentrue, the SDK will manage the action by popping the top level category.init- initializes the model where topLevelBackButtonEnabled and id are optionalreloadData- reloads the data (respecting category filter behavior as described above).willShow- triggers auto-play hint.willHide- triggers auto-pause hint.goBack- programmatically navigates back one level in the category stack, if possible.
SwiftUI reloads its components whenever the model provided to it changes. If you need to reload data without changing configuration in model then you should call reloadData on the model object provided.
Example:
import SwiftUI
import StorytellerSDK
struct ExampleSwiftUIView: View {
@StateObject var model = StorytellerClipsModel(configuration: StorytellerClipCollectionConfiguration(collectionId: "test-collection"))
var body: some View {
ZStack {
StorytellerClipsView(model: model)
}
}
}