Controlling Playback in SwiftUI
BlazeSwiftUIVideoInlinePlayerController is a SwiftUI-native controller that manages the player lifecycle and gives you programmatic access to video player control methods.
The following usage patterns are supported:
- Controller created with view: the player dies when the view dies (simple screens).
- Controller stored in a model: the player outlives the view for better performance in feeds.
The controller provides an API for standard player operations such as play and pause, full-screen transitions, and interaction control.
Implementation
Usage pattern 1: Controller created with view
struct PlayerControlsExample: View {
@StateObject private var playerController = BlazeSwiftUIVideoInlinePlayerController()
@State private var isPlaying = false
var body: some View {
VStack {
// Player view
BlazeSwiftUIVideosInlinePlayerView(
configuration: .init(
playerMode: .interactive(interactivePlyerStyle: .base()),
dataSourceType: .labels(.singleLabel("highlights")),
containerIdentifier: "main-player"
),
playerController: playerController,
embeddedState: .player(autoPlayOnStart: false)
)
.aspectRatio(16/9, contentMode: .fit)
// Control buttons
HStack(spacing: 20) {
Button(isPlaying ? "Pause" : "Play") {
if isPlaying {
playerController.pausePlayer()
} else {
playerController.resumePlayer()
}
isPlaying.toggle()
}
.buttonStyle(.bordered)
Button("Full Screen") {
playerController.enterFullScreen()
}
.buttonStyle(.bordered)
}
.padding()
}
}
}Usage pattern 2: Controller in model outlives view
class FeedItem: ObservableObject {
// Controller stored in model to outlive view instances
let playerController = BlazeSwiftUIVideoInlinePlayerController()
let id: String
init(id: String) {
self.id = id
}
}
struct FeedCellView: View {
@ObservedObject var feedItem: FeedItem
var isVisible: Bool
var body: some View {
BlazeSwiftUIVideosInlinePlayerView(
configuration: Configuration(
playerMode: .preview(previewPlayerStyle: .base()),
dataSourceType: .labels(.singleLabel("highlights")),
containerIdentifier: feedItem.id
),
playerController: feedItem.playerController,
embeddedState: isVisible ? .player(autoPlayOnStart: true) : .placeholder
)
}
}Playback control
// Resume playback
playerController.resumePlayer()
// Pause playback
playerController.pausePlayer()
// Enter full-screen mode
playerController.enterFullScreen()Interaction management
// Block user interaction.
playerController.blockInteraction()
// Unblock user interaction
playerController.unblockInteraction()Initializer
init
public init()Creates a new controller instance for managing video player operations.
The controller starts in a disconnected state and connects to a player instance automatically when passed to a BlazeSwiftUIVideosInlinePlayerView instance.
Usage example:
@StateObject private var playerController = BlazeSwiftUIVideoInlinePlayerController()Methods
resumePlayer
@MainActor
public func resumePlayer()Resumes video playback if the player is currently paused.
This method attempts to resume playback on the currently embedded video player. The operation has no effect if the player is not currently embedded or if the video is already playing.
Usage example:
Button("Play") {
playerController.resumePlayer()
}pausePlayer
@MainActor
public func pausePlayer()Pauses video playback if the player is currently playing.
This method attempts to pause playback on the currently embedded video player. The operation has no effect if the player is not currently embedded or if the video is already paused.
Usage example:
Button("Pause") {
playerController.pausePlayer()
}enterFullScreen
@MainActor
public func enterFullScreen()Transitions the player to full-screen mode with overlay controls.
This method presents the video player in a modal full-screen view controller with complete playback controls. The transition includes smooth animations and proper state management between inline and full-screen modes.
This method only works when the player is currently embedded (not in placeholder mode). Ensure the player is in an active state before calling this method.
Usage example:
Button("Full Screen") {
playerController.enterFullScreen()
}blockInteraction
@MainActor
public func blockInteraction()Blocks user interaction with the player while maintaining playback functionality through a playerController.
This method adds a transparent overlay that prevents user touches from reaching the player controls, disabling user interaction while allowing video playback to continue normally. This is useful for preventing user input during loading states, transitions, or other critical operations.
Remember to call unblockInteraction() to restore user control when appropriate. The interaction remains blocked until explicitly unblocked.
Usage example:
// Block interaction during a loading operation
playerController.blockInteraction()
// Perform async operation
Task {
await performLongRunningOperation()
playerController.unblockInteraction()
}unblockInteraction
@MainActor
public func unblockInteraction()Restores user interaction with the player after it was previously blocked.
This method removes the interaction-blocking overlay, letting users interact with player controls normally. Call it after blockInteraction() when you want to restore normal user interaction. If interaction was not previously blocked, this method has no effect.
Usage example:
// Restore interaction after completing an operation
playerController.unblockInteraction()Best practices
Lifecycle management
- Use
@StateObjectwhen creating controllers in SwiftUI views. - Store controllers in model objects for feed scenarios where players should outlive views.
- The controller automatically handles cleanup when deallocated.
State management
- Use the controller together with
EmbeddedStatefor proper state management.
Performance
- For feed views, store controllers in your data model to avoid recreation during scrolling.
- Only embed players when needed, using
EmbeddedState.placeholderinitially. - Use
Configurationchanges sparingly, as they trigger player recreation.
Error handling
The controller methods gracefully handle edge cases such as:
- The player not being embedded.
- The player already being in the requested state.
- Attempting operations on a disconnected controller.
Updated about 2 months ago
