# Creating Plugins

ByteArk Player SDK for iOS comes with a plugin system that lets you extend the Video Player to fit your project's needs. The plugins ByteArk provides (Ads, AirPlay, Lighthouse, Nielsen) use this same system — see the Integrations section for the consumer-facing plugin guides.

# How to build a plugin

To build a plugin, subclass the ByteArkPlayerPlugin class. The base class exposes a player attribute that points to the ByteArkPlayer instance using your plugin.

open class ByteArkPlayerPlugin: NSObject {
  /// The ByteArkPlayer instance — set before configure() is called
  public var player: ByteArkPlayer?
  /// Provide the plugin name
  open class var PluginName: String { get }
  public override init() {
    super.init()
  }
  /// Configure the plugin: subscribe to notifications, set up views, etc.
  open func configure() { }
  /// Tear down the plugin: unsubscribe from notifications, remove views, etc.
  open func destroy() { }
  /// Add an observer to the notification center to receive playback-engine events.
  ///
  /// - Parameters:
  ///   - notification: the notification name to register for
  ///   - block: the block that runs when the notification fires
  open func addPluginObserver(
    for notification: ByteArkPlayerPluginNotification,
    using block: @escaping (Notification) -> Void) -> any NSObjectProtocol { }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Example — a logger plugin

This example shows how to build a plugin that logs playback events:

  1. Create ByteArkPlayerLoggerPlugin that subclasses ByteArkPlayerPlugin.
  2. Override PluginName to return the plugin's name.
  3. Override configure() to subscribe to playback events and log them.
  4. Override destroy() to unsubscribe from any observers added in configure(). ByteArkPlayer calls this method before destroying the plugin.
class ByteArkPlayerLoggerPlugin: ByteArkPlayerPlugin {
  private var observerTokens: [NSObjectProtocol] = []
  override class var PluginName: String {
    "ByteArkPlayerLoggerPlugin"
  }
  override func configure() {
    var token: NSObjectProtocol
    let ByteArkPlayerNotification = ByteArkPlayerPlaybackEngineNotification.self
    token = player.addPlaybackEngineObserver(for: ByteArkPlayerNotification.ready, using: playbackEngineReady(_:))
    observerTokens.append(token)
    token = player.addPlaybackEngineObserver(for: ByteArkPlayerNotification.firstPlay, using: playbackEnginePlay(_:))
    observerTokens.append(token)
    token = player.addPlaybackEngineObserver(for: ByteArkPlayerNotification.pause, using: playbackEnginePause(_:))
    observerTokens.append(token)
    token = player.addPlaybackEngineObserver(for: ByteArkPlayerNotification.ended, using: playbackEngineEnded(_:))
    observerTokens.append(token)
  }
  override func destroy() {
    let nc = NotificationCenter.default
    for token in observerTokens {
      nc.removeObserver(token)
    }
    observerTokens.removeAll()
  }
  @objc func playbackEngineReady(notification: Notification) { print("Player Ready") }
  @objc func playbackEnginePlay(notification: Notification) { print("Playback Play") }
  @objc func playbackEnginePause(notification: Notification) { print("Playback Pause") }
  @objc func playbackEngineEnded(notification: Notification) { print("Playback End") }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Attach your plugin to ByteArkPlayer using .addPlugin(plugin:, name:) on ByteArkPlayerConfigBuilder:

let loggerPlugin = ByteArkPlayerLoggerPlugin()
do {
  let config = try ByteArkPlayerConfigBuilder()
    .item(item)
    .autoplay(true)
    .addPlugin(plugin: loggerPlugin, with: loggerPlugin.PluginName)
    .build()
  player.configure(with: config)
} catch {
}
1
2
3
4
5
6
7
8
9
10
11
12