Exiting the scenario player
This page explains how to handle the exit event of the scenario player.
ScenarioPlayer status
Considering a use-case where you only want to exit the scenario player when a user fully finished an analysis session, we want to know when the session is terminated. To this end, we provide an enum called InarixSDK.ScenarioPlayerStatus defining the different status in which the scenario player can be along its lifecycle.
enum ScenarioPlayerStatus {
case initialising // when loading mandatory data before executing a scenario
case ready // when all mandatory data are loaded and the scenario player is ready
case interacting // when a user is interacting with the scenario player
case processing // when the scenario player is processing an analysis
case terminated // when the scenario player has been prematurely terminated by the end-user, no interaction or addition can be made.
case finished // when all the processing is finished but the scenario player isn't closed
case closed // when the scenario player has been closed, no interaction or addition can be made.
}Now that we know the several status of the scenario player, we want to observe it. You can register a listener following the PlayerStatusObserver protocol to the Inarix SDK's publisher for the scenario player status using the InarixSDK.ScenarioPlayerStatusPublisher.shared.addObserver(observer) method. Below, we are providing a simple implementation to observe the scenario player status lifecycle and then deciding if we want to display the ScenarioPlayerView or not.
ViewModel
First, our ViewModel inherit from InarixSDK.PlayerStatusObserver and implement a new method called onStatusChange listening on the scenario player's status. We've added an internal private member called playerStatus storing the current status for the view to observe.
import Foundation
import InarixFramework
extension ContentView {
@Observable
class ViewModel: InarixSDK.ScenarioPlayer.StatusObserver {
private(set) var displayPlayer = false
private(set) var ready = false
private(set) var player: InarixSDK.ScenarioPlayer!
private(set) var playerStatus: InarixSDK.ScenarioPlayer.Status?
func onStatusChange(status: InarixSDK.ScenarioPlayer.Status) {
// Handling player status change here
self.playerStatus = status
if self.playerStatus == .terminated || self.playerStatus == .finished {
try? self.player.close()
self.setDisplayPlayer(value: false)
}
}
func setDisplayPlayer(value: Bool) {
self.displayPlayer = value
}
func setupPlayer() {
self.player = InarixSDK.ScenarioPlayer()
// Register self as an observer of the player status
try? self.player.listenOn(eventType: .status, observer: self)
Task { @MainActor in
do {
try await self.player.loadScenario(id: 784)
} catch let err {
debugPrint("Couldn't load scenario: \(err)")
return
}
do {
try self.player.start()
self.ready = true
} catch let err {
debugPrint("Couldn't start scenario player: \(err)")
return
}
}
}
}
}Close(force: true)
Ideally, the close() method should be used to gracefully shut down the SDK (player) object once all actions have completed.
However, in exceptional cases where you need to immediately stop the SDK during an active state (e.g., due to an error, user action, or lifecycle change), you can forcefully close it using the force parameter
try? self.player.close(force: true) ⚠️ Forcing a close while the player is active may interrupt ongoing operations or media playback. Only use this when necessary.
Close(kill:true)
- Purpose: Terminates the SDK immediately, regardless of its current state (even if in the background).
- Behaviour: Unlike force, this bypasses all cleanup or safety checks — like a “hard kill.”
- Usage example:
try? self.player.close(kil: true)- Use case: When the host app cannot locate or communicate with the SDK instance safely — e.g., the SDK is stuck, backgrounded, or non-responsive.
- Effect: Ends the SDK instantly, without guaranteeing graceful teardown.
Note: ☝️ In some cases, a force close may fail if the SDK instance is running in the background and the host app cannot determine or access its current state to shut it down safely. In such situations, the host app can use the kill parameter to immediately terminate the SDK instance at any time, regardless of its state.
View
Now that we know the status of the scenario player, we can use the view model playerStatus member to decide either we display the ScenarioPlayerView or not. We proposed an implementation below:
import SwiftUI
struct ContentView: View {
@State private var viewModel = ViewModel()
var body: some View {
if viewModel.playerStatus != nil && (viewModel.playerStatus == .terminated || viewModel.playerStatus == .finished || viewModel.playerStatus == .closed) {
VStack {
Text("Session terminated")
}
} else if viewModel.ready && viewModel.displayPlayer {
InarixSDK.ScenarioPlayerView(player: viewModel.player)
} else {
VStack {
Button("Launch player") {
viewModel.setDisplayPlayer(value: true)
}
.disabled(!viewModel.ready)
}
.padding()
.onAppear {
viewModel.setupPlayer()
}
}
}
}
#Preview {
ContentView()
}
TheScenarioPlayerViewonly serves as a "window" on the internal state of theScenarioPlayer. Technically, you can decide to display the view or not at any moment.
Updated about 2 months ago
Ok, now you know how to listen on the ScenarioPlayerStatus, but what about error handling? 🧐
