Respond to player events (iOS v3)

In order to respond to player events, you can notify your event-handlers via delegation and/or notification.


Delegation is a pattern useful for modeling one-to-one relationships, such as when all the logic for responding to a player's events can be handled by the view controller in which the player is embedded. You implement this pattern by having an object adopt the JWPlayerDelegate protocol, and assigning it to the player's delegate property.

The protocol provides delegate methods for each player event; for more information please review the JWPlayerDelegate protocol in our API Reference document, or in the JWPlayerDelegate.h file in the SDK package directly.

The following snippet shows a view controller adopting the protocol, and waiting until the player is ready (the onReady event) before adding it to the view hierarchy.

import UIKit

class SwiftViewController: UIViewController {
    var player: JWPlayerController?
    override func viewDidLoad() {
        let config = JWConfig(contentURL: "")
        player = JWPlayerController(config: config)
        player?.delegate = self

// Declares adherence to the protocol here.
extension SwiftViewController: JWPlayerDelegate {
// Fired when the player has initialized in HTML5 and is ready for playback.
    func onReady(_ event: JWEvent & JWReadyEvent) {
#import <JWPlayer_iOS_SDK/JWPlayerController.h>

// adopts the protocol here
@interface ObjCViewController : UIViewController <JWPlayerDelegate>

@interface ObjCViewController ()
@property (nonatomic) JWPlayerController *player;

@implementation ObjCViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    JWConfig *config = [JWConfig configWithContentURL:@""];
    self.player = [[JWPlayerController alloc]initWithConfig:config];
    self.player.delegate = self;

// MARK: - JWPlayerDelegate
- (void)onReady:(JWEvent<JWReadyEvent> *)event {
    [self.view addSubview:self.player.view];



This pattern is the flip-side of the Observer pattern, and so it is useful for modeling one-to-many relationships, such as when you want to keep reactive player logic, UI responses, yours or a third-party's analytics integrations, and other distinct event-driven logics separate from one another -- or simply as a way to further decouple event-driven logic from the UI.

The SDK supports this pattern by posting notifications to the default NotificationCenter. Every callback notification has an “event” entry in its userInfo dictionary, together with the additional parameters described in the following sections.

The following snippet shows one possible naive implementation of subscribing to the SDK's posted notifications.

func subscribeToNotifications() {
    _ = NotificationCenter.default.addObserver(forName: .metaData, object: nil, queue: nil) {
(metaDataNotification) in
        let metaData = metaDataNotification.userInfo?["metaData"] as! [String: Any?]
// PrettyPrinter -
        print(PrettyPrinter.print(json: metaData))

// Allows 'Swifty' shorthand dot-notation
extension Notification.Name {
    static var metaData: Notification.Name {
        return Notification.Name(rawValue: JWMetaDataAvailableNotification) }
-(void)subscribeToNotifications {
    void (^metadataHandler)(NSNotification*) = ^(NSNotification * _Nonnull note) {
        if ([NSJSONSerialization isValidJSONObject:note.userInfo]) {
            NSError *error;
            NSData *metadataData = [NSJSONSerialization dataWithJSONObject:note.userInfo
            if (error) {
                NSLog(@"%@", error.localizedDescription);
            } else {
                NSString *metadata = [[NSString alloc] initWithData:metadataData encoding:NSUTF8StringEncoding];
                NSLog(@"%@", metadata);
    [NSNotificationCenter.defaultCenter addObserverForName:JWMetaDataAvailableNotification object:nil queue:nil usingBlock:metadataHandler];


  • onMeta: Fired shortly after the video starts to play.
    * metaData: Object containing the new metadata. This can be metadata hidden in the media (XMP, ID3, keyframes) or metadata broadcasted by the playback provider (bandwidth, quality switches).


A set of events reporting changes in the player state. Each event (except onReady) has two params newState and oldState that represent current state after event and previous state.

  • onPlayAttempt: Triggered the instant a user attempts to play a file.
  • onFirstFrame: Triggered by a video's first frame event (Or the instant an audio file begins playback).
  • onReady: The player is created and ready to be used.
  • onIdle: The player stopped playing.
  • onComplete: The player has done playing current media.
  • onBuffer: The player is buffering media.
  • onBufferChange: Fired when the currently playing item loads additional data into its buffer.
  • onPlay: The player started to play media.
  • onPause: The player is paused.


  • onTime: Fired continuously while the player is playing media. May get fired up to 10 times a second.
    duration: the duration of the media currently being played (not applicable for lie streams).
    position: current playback position in seconds (not applicable for live streams).
  • onSeek: Fired after a seek has been requested either by scrubbing the controlbar or through the API.
    • offset: The user requested position to seek to (in seconds).
    • position: The position of the player before the player seeks (in seconds).


Fired when the player changes to/from fullscreen mode.

  • onFullscreen: Parameters:
    * state: integer representing is the player is in fullscreen (1) or windowed mode (0).


Set of events related to advertisements.

  • onAdRequest: Fired whenever an ad is requested by the player.
  • onAdSkipped: Fired when the user taps skip button during ad.
  • onAdComplete: Fired when ad is done playing.
  • onAdImpression: Fired when ad shows up on the screen.
  • onAdStarted: VPAID-only. Will trigger when a VPAID ad creative signals to our player that it is starting. This differs from adImpression since the advertisement may not yet be visible. Fires after the first onAdPlay event.
  • onAdMeta: Fired when new metadata has been broadcasted by the player during an Ad.
  • onAdPlay: Fired when ad start to play or is resumed after pause.
  • onAdPause: Fired when ad is paused.
  • onAdCompanions: Fired whenever an ad contains companions.
  • onAdError: Fired when ad can’t be played for any reason (onError event is fired at the same time).


Continuous ad playback time update.

  • onAdTime


  • onAdClick: Fired when the user taps the ad (omitted if openSafariOnAdClick is set to true)


Fired when the player encounters any errors.

  • onSetupError: Fired when an error occurs before setup is complete, or in other words before the onReady Event.
  • onError: Fired when an error occurs after setup.
  • onAdError: Fired when an error occurs during ad playback.


  • onCaptionsList: Parameters:
    track: number of the active captions track.
    tracks: array of all available captions tracks.
  • onCaptionsChange: Parameters:
    track: number of the active captions track.
    tracks: array of all available captions tracks.


  • onLevels: Parameters:
    currentQuality: number of the current quality level from the list.
    levels: list of available quality levels.
  • onLevelsChanged: Parameters:
    currentQuality: number of the current quality level from the list.
    levels: list of available quality levels.
  • onVisualQuality: Parameters:
    • mode: The type of quality selection that has been enabled with the player. This will read auto when a user is relying on our automatic quality determination or manual when a user has selected a static quality.
    • reason: Why the quality was changed. This can be initial choice.
    • label: Information about the quality that was changed. This will display your label, bitrate, index, and resolution.


  • onAudioTracks: Parameters:
    • levels: Array with audio tracks from the player.
  • onAudioTrackChanged: Parameters:
    • currentTrack: Index of the newly selected audio track in the audio tracks array.