From 7239027f5ca97a1499fcbe2ded9bd47325f4768c Mon Sep 17 00:00:00 2001 From: Wootae Jeon Date: Wed, 1 Feb 2023 14:01:19 -0800 Subject: [PATCH] feat/swiftui_banner_mrec (#190) https://app.asana.com/0/573104092700345/1203788313801344/f https://user-images.githubusercontent.com/27931661/215855424-e1c787a1-1267-4c29-ba01-31cd6ba1e71d.MP4 https://user-images.githubusercontent.com/27931661/215855406-ed928ea8-91d6-4651-b90b-6727094b702f.MP4 --------- Co-authored-by: Harry Arakkal --- .../project.pbxproj | 32 +++- .../Base Classes/MAAdViewSwiftUIWrapper.swift | 160 ++++++++++++++++++ .../ALMAXSwiftUIBannerAdViewController.swift | 20 +++ .../Banners/UI/ALMAXSwiftUIBannerAdView.swift | 98 +++++++++++ .../ALMAXSwiftUIMRecAdViewController.swift | 20 +++ .../MAX/MRECs/UI/ALMAXSwiftUIMRecAdView.swift | 98 +++++++++++ .../Base.lproj/Main.storyboard | 72 ++++++++ 7 files changed, 498 insertions(+), 2 deletions(-) create mode 100644 AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Base Classes/MAAdViewSwiftUIWrapper.swift create mode 100644 AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/ALMAXSwiftUIBannerAdViewController.swift create mode 100644 AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/UI/ALMAXSwiftUIBannerAdView.swift create mode 100644 AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/ALMAXSwiftUIMRecAdViewController.swift create mode 100644 AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/UI/ALMAXSwiftUIMRecAdView.swift diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift.xcodeproj/project.pbxproj b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift.xcodeproj/project.pbxproj index a1ac22341b..0f5146c44b 100644 --- a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift.xcodeproj/project.pbxproj +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift.xcodeproj/project.pbxproj @@ -3,10 +3,15 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ + 1055D8A32984A18700228C1B /* MAAdViewSwiftUIWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1055D8A22984A18700228C1B /* MAAdViewSwiftUIWrapper.swift */; }; + 1055D8A52984A19400228C1B /* ALMAXSwiftUIMRecAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1055D8A42984A19400228C1B /* ALMAXSwiftUIMRecAdViewController.swift */; }; + 1055D8A72984A1A200228C1B /* ALMAXSwiftUIMRecAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1055D8A62984A1A200228C1B /* ALMAXSwiftUIMRecAdView.swift */; }; + 1055D8AB2984A1BC00228C1B /* ALMAXSwiftUIBannerAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1055D8A92984A1BC00228C1B /* ALMAXSwiftUIBannerAdView.swift */; }; + 1055D8AC2984A1BC00228C1B /* ALMAXSwiftUIBannerAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1055D8AA2984A1BC00228C1B /* ALMAXSwiftUIBannerAdViewController.swift */; }; 1DDCE59D242AE564007EAC8D /* ALMAXFrameLayoutBannerAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DDCE596242AE564007EAC8D /* ALMAXFrameLayoutBannerAdViewController.swift */; }; 1DDCE59E242AE564007EAC8D /* ALMAXInterfaceBuilderBannerAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DDCE597242AE564007EAC8D /* ALMAXInterfaceBuilderBannerAdViewController.swift */; }; 1DDCE59F242AE564007EAC8D /* ALMAXAutoLayoutBannerAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DDCE598242AE564007EAC8D /* ALMAXAutoLayoutBannerAdViewController.swift */; }; @@ -52,6 +57,11 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 1055D8A22984A18700228C1B /* MAAdViewSwiftUIWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MAAdViewSwiftUIWrapper.swift; sourceTree = ""; }; + 1055D8A42984A19400228C1B /* ALMAXSwiftUIMRecAdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXSwiftUIMRecAdViewController.swift; sourceTree = ""; }; + 1055D8A62984A1A200228C1B /* ALMAXSwiftUIMRecAdView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXSwiftUIMRecAdView.swift; sourceTree = ""; }; + 1055D8A92984A1BC00228C1B /* ALMAXSwiftUIBannerAdView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXSwiftUIBannerAdView.swift; sourceTree = ""; }; + 1055D8AA2984A1BC00228C1B /* ALMAXSwiftUIBannerAdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXSwiftUIBannerAdViewController.swift; sourceTree = ""; }; 1DDCE596242AE564007EAC8D /* ALMAXFrameLayoutBannerAdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXFrameLayoutBannerAdViewController.swift; sourceTree = ""; }; 1DDCE597242AE564007EAC8D /* ALMAXInterfaceBuilderBannerAdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXInterfaceBuilderBannerAdViewController.swift; sourceTree = ""; }; 1DDCE598242AE564007EAC8D /* ALMAXAutoLayoutBannerAdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ALMAXAutoLayoutBannerAdViewController.swift; sourceTree = ""; }; @@ -110,12 +120,22 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1055D8A82984A1BC00228C1B /* UI */ = { + isa = PBXGroup; + children = ( + 1055D8A92984A1BC00228C1B /* ALMAXSwiftUIBannerAdView.swift */, + ); + path = UI; + sourceTree = ""; + }; 1DDCE595242AE564007EAC8D /* Banners */ = { isa = PBXGroup; children = ( + 1055D8A82984A1BC00228C1B /* UI */, 1DDCE598242AE564007EAC8D /* ALMAXAutoLayoutBannerAdViewController.swift */, 1DDCE596242AE564007EAC8D /* ALMAXFrameLayoutBannerAdViewController.swift */, 1DDCE597242AE564007EAC8D /* ALMAXInterfaceBuilderBannerAdViewController.swift */, + 1055D8AA2984A1BC00228C1B /* ALMAXSwiftUIBannerAdViewController.swift */, ); path = Banners; sourceTree = ""; @@ -139,9 +159,10 @@ 1DDCE5A2242AE5CE007EAC8D /* Base Classes */ = { isa = PBXGroup; children = ( - 1DDCE5A3242AE5CE007EAC8D /* ALHomeViewController.swift */, 1DDCE5A4242AE5CE007EAC8D /* ALBaseAdViewController.swift */, + 1DDCE5A3242AE5CE007EAC8D /* ALHomeViewController.swift */, 35C0C88527F79E090030B2F8 /* ALTextCollectionViewCell.swift */, + 1055D8A22984A18700228C1B /* MAAdViewSwiftUIWrapper.swift */, ); path = "Base Classes"; sourceTree = ""; @@ -213,6 +234,7 @@ 37B6CECD246DE9FF0068A6A4 /* ALMAXFrameLayoutMRecAdViewController.swift */, 37B6CECF246DEA300068A6A4 /* ALMAXInterfaceBuilderMRecAdViewController.swift */, 6254AC68286A5741000D3298 /* ALMAXMRecTableViewController.swift */, + 1055D8A42984A19400228C1B /* ALMAXSwiftUIMRecAdViewController.swift */, ); path = MRECs; sourceTree = ""; @@ -230,6 +252,7 @@ isa = PBXGroup; children = ( 6254AC6C286A5E90000D3298 /* ALMAXMRecTableViewCell.swift */, + 1055D8A62984A1A200228C1B /* ALMAXSwiftUIMRecAdView.swift */, ); path = UI; sourceTree = ""; @@ -389,6 +412,7 @@ E5BDBE8C243404D100F82D79 /* ALDemoInterfaceBuilderLeaderViewController.swift in Sources */, 35C0C88627F79E090030B2F8 /* ALTextCollectionViewCell.swift in Sources */, 77B6F43E279B51F70063F81D /* ALMAXTemplateNativeAdViewController.swift in Sources */, + 1055D8A32984A18700228C1B /* MAAdViewSwiftUIWrapper.swift in Sources */, 5BCB21D227445E46007218B2 /* ALDemoMRecProgrammaticViewController.swift in Sources */, E5BDBE862433F4FF00F82D79 /* ALDemoBannerZoneViewController.swift in Sources */, E5BDBE8B243404D100F82D79 /* ALDemoProgrammaticLeaderViewController.swift in Sources */, @@ -403,18 +427,22 @@ E5BDBDFE2432C4E800F82D79 /* ALDemoRewardedVideosZoneViewController.swift in Sources */, 1DDCE59F242AE564007EAC8D /* ALMAXAutoLayoutBannerAdViewController.swift in Sources */, 1DDCE5A0242AE564007EAC8D /* ALMAXRewardedAdViewController.swift in Sources */, + 1055D8A72984A1A200228C1B /* ALMAXSwiftUIMRecAdView.swift in Sources */, 37C4D0E8233D834900096894 /* main.swift in Sources */, 37B6CECE246DE9FF0068A6A4 /* ALMAXFrameLayoutMRecAdViewController.swift in Sources */, 35C0C88227F79C820030B2F8 /* ALMAXAdPlacerTableViewController.swift in Sources */, + 1055D8A52984A19400228C1B /* ALMAXSwiftUIMRecAdViewController.swift in Sources */, 77AAC0F727D806820060499A /* ALMAXManualNativeLateBindingAdViewController.swift in Sources */, 1DDCE5A6242AE5CE007EAC8D /* ALBaseAdViewController.swift in Sources */, 77B6F43D279B51F70063F81D /* ALMAXManualNativeAdViewController.swift in Sources */, 1DDCE59D242AE564007EAC8D /* ALMAXFrameLayoutBannerAdViewController.swift in Sources */, E5BDBDFA2432C4E800F82D79 /* ALDemoInterstitialBasicIntegrationViewController.swift in Sources */, + 1055D8AB2984A1BC00228C1B /* ALMAXSwiftUIBannerAdView.swift in Sources */, 3763B23723357C4B00E49783 /* ALAppDelegate.swift in Sources */, E5BDBE872433F4FF00F82D79 /* ALDemoProgrammaticBannerViewController.swift in Sources */, E5BDBFF124354C4000F82D79 /* ALEventTrackingViewController.swift in Sources */, E5BDBDFD2432C4E800F82D79 /* ALDemoRewardedVideosViewController.swift in Sources */, + 1055D8AC2984A1BC00228C1B /* ALMAXSwiftUIBannerAdViewController.swift in Sources */, 35C0C88427F79C910030B2F8 /* ALMAXAdPlacerCollectionViewController.swift in Sources */, E5BDBDFB2432C4E800F82D79 /* ALDemoInterstitialZoneViewController.swift in Sources */, ); diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Base Classes/MAAdViewSwiftUIWrapper.swift b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Base Classes/MAAdViewSwiftUIWrapper.swift new file mode 100644 index 0000000000..cec1ad32f1 --- /dev/null +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Base Classes/MAAdViewSwiftUIWrapper.swift @@ -0,0 +1,160 @@ +// +// MAAdViewSwiftUIWrapper.swift +// AppLovin MAX Demo App - Swift +// +// Created by Wootae Jeon on 1/26/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +import SwiftUI +import AppLovinSDK + +@available(iOS 13.0, *) +struct MAAdViewSwiftUIWrapper: UIViewRepresentable +{ + let adUnitIdentifier: String + let adFormat: MAAdFormat + let sdk: ALSdk + + // MAAdViewAdDelegate methods + var didLoad: ((MAAd) -> Void)? = nil + var didFailToLoadAd: ((String, MAError) -> Void)? = nil + var didDisplay: ((MAAd) -> Void)? = nil + var didFailToDisplayAd: ((MAAd, MAError) -> Void)? = nil + var didClick: ((MAAd) -> Void)? = nil + var didExpand: ((MAAd) -> Void)? = nil + var didCollapse: ((MAAd) -> Void)? = nil + var didHide: ((MAAd) -> Void)? = nil + + // MAAdRequestDelegate method + var didStartAdRequest: ((String) -> Void)? = nil + + // MAAdRevenueDelegate method + var didPayRevenue: ((MAAd) -> Void)? = nil + + func makeUIView(context: Context) -> MAAdView + { + let adView = MAAdView(adUnitIdentifier: adUnitIdentifier, adFormat: adFormat, sdk: sdk) + + adView.delegate = context.coordinator + adView.requestDelegate = context.coordinator + adView.revenueDelegate = context.coordinator + + // Set background or background color for AdViews to be fully functional + adView.backgroundColor = .black + + // Load the first ad + adView.loadAd() + + return adView + } + + func updateUIView(_ uiView: MAAdView, context: Context) {} + + func makeCoordinator() -> Coordinator + { + Coordinator(parent: self) + } +} + +@available(iOS 13.0, *) +extension MAAdViewSwiftUIWrapper +{ + class Coordinator: NSObject, MAAdViewAdDelegate, MAAdRequestDelegate, MAAdRevenueDelegate + { + private let parent: MAAdViewSwiftUIWrapper + + init(parent: MAAdViewSwiftUIWrapper) + { + self.parent = parent + } + + func didStartAdRequest(forAdUnitIdentifier adUnitIdentifier: String) + { + parent.didStartAdRequest?(adUnitIdentifier) + } + + func didLoad(_ ad: MAAd) + { + parent.didLoad?(ad) + } + + func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) + { + parent.didFailToLoadAd?(adUnitIdentifier, error) + } + + func didDisplay(_ ad: MAAd) + { + parent.didDisplay?(ad) + } + + func didFail(toDisplay ad: MAAd, withError error: MAError) + { + parent.didFailToDisplayAd?(ad, error) + } + + func didClick(_ ad: MAAd) + { + parent.didClick?(ad) + } + + func didExpand(_ ad: MAAd) + { + parent.didExpand?(ad) + } + + func didCollapse(_ ad: MAAd) + { + parent.didCollapse?(ad) + } + + func didHide(_ ad: MAAd) + { + parent.didHide?(ad) + } + + func didPayRevenue(for ad: MAAd) + { + parent.didPayRevenue?(ad) + } + } +} + +@available(iOS 13.0, *) +extension MAAdViewSwiftUIWrapper +{ + func deviceSpecificFrame() -> some View + { + modifier(MAAdViewFrame(adFormat: adFormat)) + } +} + +@available(iOS 13.0.0, *) +struct MAAdViewFrame: ViewModifier +{ + let adFormat: MAAdFormat + + func body(content: Content) -> some View + { + if ( adFormat == .banner || adFormat == .leader ) + { + // Stretch to the width of the screen for banners to be fully functional + // Banner height on iPhone and iPad is 50 and 90, respectively + content + .frame(height: (UIDevice.current.userInterfaceIdiom == .pad) ? 90 : 50) + } + else // adFormat == .mrec + { + // MREC width and height are 300 and 250 respectively, on iPhone and iPad + content + .frame(width: 300, height: 250) + } + } +} + +struct CallbackTableItem: Identifiable +{ + let id = UUID() + let callback: String +} diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/ALMAXSwiftUIBannerAdViewController.swift b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/ALMAXSwiftUIBannerAdViewController.swift new file mode 100644 index 0000000000..5c1271ee9d --- /dev/null +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/ALMAXSwiftUIBannerAdViewController.swift @@ -0,0 +1,20 @@ +// +// ALMAXSwiftUIBannerAdViewController.swift +// AppLovin MAX Demo App - Swift +// +// Created by Wootae Jeon on 1/26/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +import SwiftUI +import UIKit +import AppLovinSDK + +@available(iOS 13.0, *) +class ALMAXSwiftUIBannerAdViewController: UIHostingController +{ + required init?(coder aDecoder: NSCoder) + { + super.init(coder: aDecoder, rootView: ALMAXSwiftUIBannerAdView()) + } +} diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/UI/ALMAXSwiftUIBannerAdView.swift b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/UI/ALMAXSwiftUIBannerAdView.swift new file mode 100644 index 0000000000..c4083cec1d --- /dev/null +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/Banners/UI/ALMAXSwiftUIBannerAdView.swift @@ -0,0 +1,98 @@ +// +// ALMAXSwiftUIBannerAdView.swift +// AppLovin MAX Demo App - Swift +// +// Created by Wootae Jeon on 1/26/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +import SwiftUI +import Adjust +import AppLovinSDK + +@available(iOS 13.0, *) +struct ALMAXSwiftUIBannerAdView: View +{ + @ObservedObject private var viewModel = ALMAXSwiftUIBannerAdViewModel() + + var body: some View { + VStack { + MAAdViewSwiftUIWrapper(adUnitIdentifier: "YOUR_AD_UNIT_ID", + adFormat: .banner, + sdk: ALSdk.shared()!, + didLoad: viewModel.didLoad, + didFailToLoadAd: viewModel.didFailToLoadAd, + didDisplay: viewModel.didDisplay, + didFailToDisplayAd: viewModel.didFail, + didClick: viewModel.didClick, + didExpand: viewModel.didExpand, + didCollapse: viewModel.didCollapse, + didHide: viewModel.didHide, + didPayRevenue: viewModel.didPayRevenue) + .deviceSpecificFrame() + + callbacksTable + .frame(maxHeight: .infinity) + } + } + + var callbacksTable: some View { + List(viewModel.callbacks) { + Text($0.callback) + } + } +} + +@available(iOS 13.0, *) +class ALMAXSwiftUIBannerAdViewModel: NSObject, ObservableObject +{ + @Published fileprivate var callbacks: [CallbackTableItem] = [] + + private func logCallback(functionName: String = #function) + { + DispatchQueue.main.async { + withAnimation { + self.callbacks.append(CallbackTableItem(callback: functionName)) + } + } + } +} + +@available(iOS 13.0, *) +extension ALMAXSwiftUIBannerAdViewModel: MAAdViewAdDelegate, MAAdRevenueDelegate +{ + // MARK: MAAdDelegate Protocol + func didLoad(_ ad: MAAd) { logCallback() } + + func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { logCallback() } + + func didDisplay(_ ad: MAAd) { logCallback() } + + func didHide(_ ad: MAAd) { logCallback() } + + func didClick(_ ad: MAAd) { logCallback() } + + func didFail(toDisplay ad: MAAd, withError error: MAError) { logCallback() } + + // MARK: MAAdViewAdDelegate Protocol + func didExpand(_ ad: MAAd) { logCallback() } + + func didCollapse(_ ad: MAAd) { logCallback() } + + // MARK: MAAdRevenueDelegate Protocol + func didPayRevenue(for ad: MAAd) + { + logCallback() + + let adjustAdRevenue = ADJAdRevenue(source: ADJAdRevenueSourceAppLovinMAX)! + adjustAdRevenue.setRevenue(ad.revenue, currency: "USD") + adjustAdRevenue.setAdRevenueNetwork(ad.networkName) + adjustAdRevenue.setAdRevenueUnit(ad.adUnitIdentifier) + if let placement = ad.placement + { + adjustAdRevenue.setAdRevenuePlacement(placement) + } + + Adjust.trackAdRevenue(adjustAdRevenue) + } +} diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/ALMAXSwiftUIMRecAdViewController.swift b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/ALMAXSwiftUIMRecAdViewController.swift new file mode 100644 index 0000000000..826c67273f --- /dev/null +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/ALMAXSwiftUIMRecAdViewController.swift @@ -0,0 +1,20 @@ +// +// ALMAXSwiftUIMRecAdViewController.swift +// AppLovin MAX Demo App - Swift +// +// Created by Wootae Jeon on 1/27/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +import SwiftUI +import UIKit +import AppLovinSDK + +@available(iOS 13.0, *) +class ALMAXSwiftUIMRecAdViewController: UIHostingController +{ + required init?(coder aDecoder: NSCoder) + { + super.init(coder: aDecoder, rootView: ALMAXSwiftUIMRecAdView()) + } +} diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/UI/ALMAXSwiftUIMRecAdView.swift b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/UI/ALMAXSwiftUIMRecAdView.swift new file mode 100644 index 0000000000..54383f5447 --- /dev/null +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/MAX/MRECs/UI/ALMAXSwiftUIMRecAdView.swift @@ -0,0 +1,98 @@ +// +// ALMAXSwiftUIMRecAdView.swift +// AppLovin MAX Demo App - Swift +// +// Created by Wootae Jeon on 1/27/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +import SwiftUI +import Adjust +import AppLovinSDK + +@available(iOS 13.0, *) +struct ALMAXSwiftUIMRecAdView: View +{ + @ObservedObject private var viewModel = ALMAXSwiftUIMRecAdViewModel() + + var body: some View { + VStack { + MAAdViewSwiftUIWrapper(adUnitIdentifier: "YOUR_AD_UNIT_ID", + adFormat: .mrec, + sdk: ALSdk.shared()!, + didLoad: viewModel.didLoad, + didFailToLoadAd: viewModel.didFailToLoadAd, + didDisplay: viewModel.didDisplay, + didFailToDisplayAd: viewModel.didFail, + didClick: viewModel.didClick, + didExpand: viewModel.didExpand, + didCollapse: viewModel.didCollapse, + didHide: viewModel.didHide, + didPayRevenue: viewModel.didPayRevenue) + .deviceSpecificFrame() + + callbacksTable + .frame(maxHeight: .infinity) + } + } + + var callbacksTable: some View { + List(viewModel.callbacks) { + Text($0.callback) + } + } +} + +@available(iOS 13.0, *) +class ALMAXSwiftUIMRecAdViewModel: NSObject, ObservableObject +{ + @Published fileprivate var callbacks: [CallbackTableItem] = [] + + private func logCallback(functionName: String = #function) + { + DispatchQueue.main.async { + withAnimation { + self.callbacks.append(CallbackTableItem(callback: functionName)) + } + } + } +} + +@available(iOS 13.0, *) +extension ALMAXSwiftUIMRecAdViewModel: MAAdViewAdDelegate, MAAdRevenueDelegate +{ + // MARK: MAAdDelegate Protocol + func didLoad(_ ad: MAAd) { logCallback() } + + func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { logCallback() } + + func didDisplay(_ ad: MAAd) { logCallback() } + + func didHide(_ ad: MAAd) { logCallback() } + + func didClick(_ ad: MAAd) { logCallback() } + + func didFail(toDisplay ad: MAAd, withError error: MAError) { logCallback() } + + // MARK: MAAdViewAdDelegate Protocol + func didExpand(_ ad: MAAd) { logCallback() } + + func didCollapse(_ ad: MAAd) { logCallback() } + + // MARK: MAAdRevenueDelegate Protocol + func didPayRevenue(for ad: MAAd) + { + logCallback() + + let adjustAdRevenue = ADJAdRevenue(source: ADJAdRevenueSourceAppLovinMAX)! + adjustAdRevenue.setRevenue(ad.revenue, currency: "USD") + adjustAdRevenue.setAdRevenueNetwork(ad.networkName) + adjustAdRevenue.setAdRevenueUnit(ad.adUnitIdentifier) + if let placement = ad.placement + { + adjustAdRevenue.setAdRevenuePlacement(placement) + } + + Adjust.trackAdRevenue(adjustAdRevenue) + } +} diff --git a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Supporting Files/Base.lproj/Main.storyboard b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Supporting Files/Base.lproj/Main.storyboard index 8357281138..e777ce8cdf 100644 --- a/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Supporting Files/Base.lproj/Main.storyboard +++ b/AppLovin MAX Demo App - Swift/AppLovin MAX Demo App - Swift/Supporting Files/Base.lproj/Main.storyboard @@ -648,6 +648,22 @@ + + + + + + + + + + + + + + + + @@ -887,6 +903,22 @@ + + + + + + + + + + + + + + + + @@ -1437,6 +1469,26 @@ + + + + + + + + + + + + + + @@ -1539,6 +1591,26 @@ + + + + + + + + + + + + + +