# Multiple players for iOS hil div div p With span v4.4.0 of the Wowza Flowplayer Apple SDK, we added multiple player support to integrate more than one player simultaneously in your iOS applications. p This feature is helpful when you intend to play two different media sources within the same user interface. Both player instances containing the media can be controlled separately as they function independently of each other. Info To view an example of this feature, see the iOS Example application in our apple-sdk-releases repository. The multi-player examples contain a video-on-demand (VOD) sample that incorporates two different players in the same view. p For information related to listening to events, managing media playback, and handling errors, see these pages: ul li a Listen for events li a Manage media playback li a Handle errors p img ## Identify a player instance To manage each view instance, you can use the `id` property of the [FlowplayerAPI protocol](/docs/wowza-flowplayer/apple-sdk/manage-media-playback/#properties). By default, the view randomly generates and emits the value of this property. However, you can also [set a custom string identifier](/docs/wowza-flowplayer/apple-sdk/ios-features/multiple-players/#set-a-custom-player-identifier). This section provides examples of how to identify a player instance, then use the delegate pattern or the notification dispatch mechanism to perform a certain action. ### Use delegation to identify a player You can use the delegate pattern to listen for and capture the `id` of a view that's triggered a specific event. The following example monitors changes in the player's state and responds based on which player instance triggered the state change. For an event listeners reference, see [Listen for events with the delegate method](/docs/wowza-flowplayer/apple-sdk/listen-for-events/#listen-with-the-delegate-method). ##### Example ```swift // Declare player instances let mainPlayer = FlowplayerView() let secondaryPlayer = FlowplayerView() // Set delegate property and conform to FlowplayerDelegate protocol mainPlayer.delegate = self secondaryPlayer.delegate = self // Use FlowplayerDelegate protocol to observe and respond to player state changes func player(player: FlowplayerAPI, didChangeState state: PlayerState) { // Compare id property of mainPlayer variable and player parameter guard mainPlayer.id == player.id else { // If not equal, indicate event was triggered by secondaryPlayer instance print("secondaryPlayer triggered this event") return } // If equal, indicate event was triggered by mainPlayer instance print("mainPlayer changed the state to: \(state)") } ``` ### Use notifications to identify a player You can also use the notification dispatch mechanism in the Wowza Flowplayer Apple SDK to detect the `id` of the player and respond to player events. The following code snippet sets up a notification observer for changes in the player's state. When a state notification is received, it checks the player's identifier and performs a certain action based on which player triggered the event. For more information, see [Listen for events with the NotificationCenter](/docs/wowza-flowplayer/apple-sdk/listen-for-events/#listen-with-the-notificationcenter). ##### Example ```swift // Declare player instances let mainPlayer = FlowplayerView() let secondaryPlayer = FlowplayerView() // Register observer for flowplayerDidChangeState notification NotificationCenter.default.addObserver( self, selector: #selector(onReceivedState), name: .flowplayerDidChangeState, object: nil ) // Call onReceivedState method when notification is received @objc private func onReceivedState(_ notification: Notification) { guard // Retrieve id from notification's user info and check if it matches mainPlayer id let id = notification.userInfo?[\FlowplayerAPI.id] as? String, mainPlayer.id == id else { // If not equal, indicate event was triggered by secondaryPlayer instance print("myOtherPlayer triggered this event") return } guard let state = notification.object as? PlayerState else { return } // If equal, indicate event was triggered by mainPlayer instance print("mainPlayer changed state to: \(state)") } ``` ## Set a custom player identifier The player's default behavior randomly generates and emits the value of an `id` property to identify each player instance. You can also set a player `id` that uses a custom string. This is helpful when you have a requirement to use a specific identifier for your player instance. To set up a player with a custom `id`, use this `FlowplayerView` initializer: ```swift public init(avPlayer: AVPlayer? = nil, id: String? = nil) ``` When you [initialize a FlowplayerView programmatically](/docs/wowza-flowplayer/apple-sdk/set-up-the-player/#add-flowplayerview-programmatically), add the initializer and replace the `[some-id]` placeholder with a desired ID value: ```swift // Create instance of FlowplayerView, initialize it with avPlayer and id parameters let flowplayerView = FlowplayerView(avPlayer: nil, id: "[some-id]") ``` The `avPlayer` and `id` parameters are optional. If `avPlayer` is omitted, the `FlowplayerView` class creates its own `AVPlayer` instance instead of using an instance you provide. ## Feature Limitations This section outlines limitations to consider when using multiple players at the same time in your iOS applications. ### Handling full-screen mode If using the `FlowplayerView` class to render multiple player instances at once, some limitations exist when managing full-screen behavior. Multiple players in the same `UIViewController` class can't enter the full-screen display simply with device rotation. This occurs because each `FlowplayerView` instance doesn't know what triggered the orientation change, which could have been caused by user action or another player instance. For this reason, disable the following properties for all `FlowplayerView` instances used inside a single `UIViewController` class: ```swift // Player isn't forced into full-screen mode when orientation change occurs flowplayerView.orientationControlsFullscreen = false ``` ```swift // Player isn't forced to rotate into landscape mode when entering full-screen mode flowplayerView.fullscreenControlsOrientation = false ``` info If you would still like to have a single `FlowplayerView` instance go into full-screen mode when the device orientation changes, set the `fullscreenControlsOrientation` property to `true` for that specific instance. Make sure to disable the same property for all other instances of `FlowplayerView`. To learn more, see [Enter or exit full-screen mode](/docs/wowza-flowplayer/apple-sdk/ios-features/player-controls/#enter-or-exit-full-screen-mode) and the [FlowplayerViewAPI properties](/docs/wowza-flowplayer/apple-sdk/manage-media-playback/#flowplayerviewapi).