Last active
July 6, 2022 15:55
-
-
Save AmitaiB/2dee746618fc2916637a08e3eb7c21e6 to your computer and use it in GitHub Desktop.
Quick and dirty JWAdCompanion implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In a JWPlayerViewController, with player configured, etc. | |
// For example, our BPA: https://github.com/jwplayer/jwplayer-ios-bestPracticeApps | |
// Override the implementation of this JWAdDelegate method, | |
// which reports when any ad event is emitted by the player. | |
override func jwplayer(_ player: AnyObject, adEvent event: JWAdEvent) { | |
super.jwplayer(player, adEvent: event) // When overriding (only), must call the `super` method. | |
if let companions = event[.companions] as? [JWAdCompanion] { | |
handleCompanion(companions.first) | |
} | |
} | |
func handleCompanion(_ ad: JWAdCompanion?) { | |
switch ad!.type { | |
case .`static`: | |
handleStaticImage(ad) | |
case .html: | |
handleHTML(ad) | |
case .iframe: | |
handleiFrame(ad) | |
default: | |
break | |
} | |
} | |
func handleStaticImage(_ ad: JWAdCompanion?) { | |
guard | |
let ad = ad, | |
ad.type == .`static`, | |
// get the concrete object from the protocol | |
let playerView = playerView as? JWPlayerView | |
else { return } | |
// Layout the companion ad view under the player with JWAdCompanion.size | |
let adOrigin = CGPoint(x: playerView.left, y: playerView.bottom) | |
let adImageView = UIImageView(frame: CGRect(origin: adOrigin, size: ad.size)) | |
// Get the image with JWAdCompanion.resource | |
let adImageData = try! Data(contentsOf: ad.resource) | |
adImageView.image = UIImage(data: adImageData) | |
// Assign the UI action with JWAdCompanion.clickUrl | |
// for simplicity, using 3rd party pod https://cocoapods.org/pods/Actions | |
let tapGesture = UITapGestureRecognizer { present(SFSafariViewController(url: ad.clickUrl), animated: true) } | |
adImageView.addGestureRecognizer(tapGesture) | |
// Handle event reporting — JWAdCompanion.creativeView is an `Array` of `String`s | |
// that contain the info, e.g. the IAB's VAST §3.14 example: http://server1.com/start.jpg and .../complete.jpg | |
// The developer, knowing what to expect, can handle this accordingly. | |
if let pixels = ad.creativeView { | |
pixels.forEach { handleCompanionEventPixel($0) } | |
} | |
} | |
// Your analytics server's requirements determines what goes here. The following is hypothetical: | |
func handleCompanionEventPixel(_ pixel: String) { | |
guard let pixelTarget = URL(string: pixel) | |
else { return } | |
var eventRequest = URLRequest(url: pixelTarget) | |
eventRequest.httpMethod = "PUT" | |
eventRequest.allHTTPHeaderFields = [ | |
"Content-Type": "application/json", | |
"Accept": "application/json", | |
"SomeCustomHeaderMaybeAnID": UUID().uuidString | |
] | |
let task = URLSession.shared.dataTask(with: eventRequest) | |
task.resume() | |
} | |
func handleHTML(_ ad: JWAdCompanion?) { | |
// perhaps a WKWebView? | |
} | |
func handleiFrame(_ ad: JWAdCompanion?) { | |
// ditto? | |
} | |
// Helpful when using frames | |
extension UIView { | |
var width: CGFloat { frame.size.width } | |
var height: CGFloat { frame.size.height } | |
var left: CGFloat { frame.origin.x } | |
var right: CGFloat { left + width } | |
var top: CGFloat { frame.origin.y } | |
var bottom: CGFloat { top + height } | |
} |
Author
AmitaiB
commented
Jul 5, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment