SwiftUI Wrapper Integration

Last Updated on: 17 Oct, 2023

This topic provides a comprehensive guide on seamlessly integrating various types of ads (including banner, interstitial, native, and rewarded) into your SwiftUI application using the Meson SDK.

BEFORE YOU START

Initialize SDK

For iOS 14 and later, use the WindowGroup onChange method in your App file to initialize the SDK.

@main
struct MesonSwiftUIApp: App {
    @Environment(\.scenePhase) private var scenePhase
    var body: some Scene {
       WindowGroup {
            ContentView()
        }.onChange(of: scenePhase) { scenePhase in
         if scenePhase == .active {
                Meson.initialize(sdkConfiguration: MesonSdkConfiguration(appId: "YOUR-APP-ID")) { error in
                 if error == nil {
                        print("MesonSDK initialized successfully")
                  }
              }
            }
        }
    }
}

Integrate Banner Ad

Follow these steps to integrate Banner Ads in SwiftUI:

  1. Retrieve the banner ad unit ID from the portal.
  2. Decide banner size.
  3. Create BannerView in custom UIViewControllerRepresentable type.
  4. Create class BannerViewController in BannerView.
  5. Initialize the banner in BannerView init.
  6. Create a Coordinator object to pass the viewController from the UIViewRepresentable, confirm MesonBannerDelegate ,and handle delegate methods.
  7. In makeUIViewController, assign delegate to banner, add banner as subview in bannerViewController, load the banner, and return the bannerViewController.
struct BannerView: UIViewControllerRepresentable {
    class BannerViewController: UIViewController {}

    typealias UIViewControllerType = BannerViewController
    
    let adView: MesonBanner
    let bannerViewController = BannerViewController()
    
    init(width: CGFloat, height: CGFloat) {
        adView = MesonBanner(adUnitId: "YOUR-BANNER-ADUNIT-ID", adSize: CGSize(width: width, height: height))
    }
    
    func makeUIViewController(context: Context) -> BannerViewController {
        adView.delegate = context.coordinator
        bannerViewController.view.addSubview(adView)
        
        adView.load()
        
        return bannerViewController
    }
    
    func updateUIViewController(_ uiViewController: BannerViewController, context: Context) {}

    func makeCoordinator() -> Coordinator {
        Coordinator(viewController: bannerViewController)
    }
}

extension BannerView {
    class Coordinator: NSObject, MesonBannerDelegate {
        let viewController: BannerViewController
        
        init(viewController: BannerViewController) {
            self.viewController = viewController
        }
        
        func viewControllerForMesonBannerFullScreen() -> UIViewController {
            viewController
        }
        
        func mesonBannerDidLoad(_ banner: MesonBanner) {
            print("\(#function)")
        }
        
        func mesonBannerDidFailToLoad(_ banner: MesonBanner, error: Error) {
            print("\(#function), error: \(error.localizedDescription)")

        }
        
        func mesonBannerDidClick(_ banner: MesonBanner, params: [String : Any]?) {
            print("\(#function)")

        }
        
        func mesonBannerUserWillLeaveApplication(_ banner: MesonBanner) {
            print("\(#function)")

        }
        
        func mesonBannerWillPresentScreen(_ banner: MesonBanner) {
            print("\(#function)")

        }
        
        func mesonBannerDidPresentScreen(_ banner: MesonBanner) {
            print("\(#function)")

        }
        
        func mesonBannerWillCollapseScreen(_ banner: MesonBanner) {
            print("\(#function)")

        }
        
        func mesonBannerDidCollapseScreen(_ banner: MesonBanner) {
            print("\(#function)")

        }
        
        func mesonBannerImpression(_ banner: MesonBanner, adData: MesonAdData?) {
            print("\(#function)")

        }
    }
}

Add Banner Ad to View Hierarchy

Add UIViewControllerRepresentable to your content view's hierarchy.

import SwiftUI

struct BannerContentView: View {
    var body: some View {
        BannerView(width: 320, height: 50)
            .frame(width: 320, height: 50)
    }
}

Integrate Interstitial Ad

Follow these steps to integrate Interstitial Ads in SwiftUI:

  1. Retrieve the interstitial ad unit ID from the portal.
  2. Create InterstitialAdRepresentable in custom UIViewControllerRepresentable type.
  3. Create object viewController in InterstitialAdRepresentable.
  4. Return viewController in makeUIViewController function.
  5. Create class InterstitialAdCoordinator and confirm MesonInterstitialDelegate.
  6. Create MesonInterstitial ad object in InterstitialAdCoordinator.
  7. Create function loadAd in the InterstitialAdCoordinator to initialize and load the interstitial ad.
  8. Create function showAd in the InterstitialAdCoordinator to show the interstitial ad.
  9. Implement delegates in MesonInterstitialDelegate.
struct InterstitialAdRepresentable: UIViewControllerRepresentable {
    let viewController = UIViewController()
    
    func makeUIViewController(context: Context) -> some UIViewController {
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}

class InterstitialAdCoordinator: NSObject, MesonInterstitialDelegate {
    private var interstitial: MesonInterstitial?
    
    func loadAd() {
        interstitial = MesonInterstitial(adUnitId: "YOUR-INTERSTITIAL-ADUNIT-ID", delegate: self)
        interstitial?.load()
    }
    
    func showAd(from viewController: UIViewController) {
        guard let interstitial = interstitial else {
            return print("Ad wasn't ready")
        }
        
        interstitial.show(from: viewController)
    }
    
    func mesonInterstitialDidLoad(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialDidFailToLoad(_ interstitial: MesonInterstitial, error: Error) {
        print("\(#function), error: \(error.localizedDescription)")
    }
    func mesonInterstitialDidFailToDisplay(_ interstitial: MesonInterstitial, error: Error) {
        print("\(#function), error: \(error.localizedDescription)")
    }
    func mesonInterstitialDidClick(_ interstitial: MesonInterstitial, params: [String : Any]?) {
        print("\(#function)")
    }
    func mesonInterstitialUserWillLeaveApplication(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialWillDisplay(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialDidDisplay(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialWillDismiss(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialDidDismiss(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialImpression(_ interstitial: MesonInterstitial, adData: MesonAdData?) {
        print("\(#function)")
    }
}

Add Interstitial Ad to View Hierarchy

  1. In your View, create objects for InterstitialAdCoordinator and InterstitialAdRepresentable.
  2. Create a computed variable to return the interstitialAdRepresentable view controller.
  3. Inside your view hierarchy, load and show the ad using coordinator.loadAd() and coordinator.showAd(from: interstitialAdRepresentable.viewController).
  4. Add interstitialAdRepresentableView in your view hierarchy.
struct InterstitialContentView: View {
    private var coordinator = InterstitialAdCoordinator()
    private let interstitialAdRepresentable = InterstitialAdRepresentable()
    
    var interstitialAdRepresentableView: some View {
        interstitialAdRepresentable
        .frame(width: .zero, height: .zero)
    }
        
    var body: some View {
        VStack {
            Button("Load Interstitial") {
                coordinator.loadAd()
            }.padding(10)
            Button("Show Interstitial") {
                coordinator.showAd(from: interstitialAdRepresentable.viewController)
            }.padding(10)
            
        }
        .background(interstitialAdRepresentableView)
    }
}

Integrate Rewarded Ad

Follow these steps to integrate Rewarded Ads in SwiftUI:

  1. Retrieve the rewarded ad unit ID from the portal.
  2. Create RewardedAdRepresentable in custom UIViewControllerRepresentable type.
  3. Create object viewController in RewardedAdRepresentable.
  4. Return the viewController in makeUIViewController function.
  5. Create class RewardedAdCoordinator and confirm MesonInterstitialDelegate.
  6. Create MesonInterstitial ad object in RewardedAdCoordinator.
  7. Create function loadAd in RewardedAdCoordinator to initialize and load the interstitial ad.
  8. Create a function showAd in the RewardedAdCoordinator to show the interstitial ad.
  9. Implement the delegates in MesonInterstitialDelegate.

struct RewardedAdRepresentable: UIViewControllerRepresentable {
    let viewController = UIViewController()
    
    func makeUIViewController(context: Context) -> some UIViewController {
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}

class RewardedAdCoordinator: NSObject, MesonInterstitialDelegate {
    private var interstitial: MesonInterstitial?
    
    func loadAd() {
        interstitial = MesonInterstitial(adUnitId: "YOUR-REWARDED-ADUNIT-ID", delegate: self)
        interstitial?.load()
    }
    
    func showAd(from viewController: UIViewController) {
        guard let interstitial = interstitial else {
            return print("Ad wasn't ready")
        }
        
        interstitial.show(from: viewController)
    }
    
    func mesonInterstitialDidLoad(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialDidFailToLoad(_ interstitial: MesonInterstitial, error: Error) {
        print("\(#function), error: \(error.localizedDescription)")
    }
    func mesonInterstitialDidFailToDisplay(_ interstitial: MesonInterstitial, error: Error) {
        print("\(#function), error: \(error.localizedDescription)")
    }
    func mesonInterstitialDidClick(_ interstitial: MesonInterstitial, params: [String : Any]?) {
        print("\(#function)")
    }
    func mesonInterstitialUserWillLeaveApplication(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialWillDisplay(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialDidDisplay(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialWillDismiss(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialDidDismiss(_ interstitial: MesonInterstitial) {
        print("\(#function)")
    }
    func mesonInterstitialImpression(_ interstitial: MesonInterstitial, adData: MesonAdData?) {
        print("\(#function)")
    }
    func mesonRewardsUnlocked(_ interstitial: MesonInterstitial, rewards: [String : Any]) {
        print("\(#function), rewards: \(rewards)")
    }
}

Add Rewarded Ad to View Hierarchy

  1. In your View, create objects for RewardedAdCoordinator and RewardedAdRepresentable.
  2. Create a computed variable to return the rewardedAdRepresentable view controller.
  3. Inside your view hierarchy, load and show the ad using coordinator.showAd(from: rewardedAdRepresentable.viewController).
  4. Add rewardedAdRepresentableView in your view hierarchy.

struct RewardedContentView: View {
    private var coordinator = RewardedAdCoordinator()
    private let rewardedAdRepresentable = RewardedAdRepresentable()
    
    var rewardedAdRepresentableView: some View {
        rewardedAdRepresentable
        .frame(width: .zero, height: .zero)
    }
        
    var body: some View {
        VStack {
            Button("Load Rewarded") {
                coordinator.loadAd()
            }.padding(10)
            Button("Show Rewarded") {
                coordinator.showAd(from: rewardedAdRepresentable.viewController)
            }.padding(10)
            
        }
        .background(rewardedAdRepresentableView)
    }
}

Integrating Native Ad

Follow the steps to integrate Native Ad in SwiftUI:

  1. Retrieve the native ad unit ID from the portal.
  2. Meson Native uses UIView that should be subclassed from MesonNativeAdView and confirms MesonNativeAdViewProtocol.
  3. Download the NativeAdView template. For more information on how to download the template, see Native.
  4. In NativeView, create NativeAdViewController class that confirms UIViewControllerRepresentable.
  5. Create NativeAdViewController class in NativeView.
  6. Create NativeAdCoordinator class implementing MesonNativeDelegate. This coordinator enables the ad's loading, viewing, and callbacks.
  7. In NativeView, create an ObservableObject for NativeAdCoordinator class to reflect changes back to the view whenever the native view's state changes.
  8. In makeUIViewController method, initialize NativeAdViewController class, assign nativeAdViewController.viewController, and return the view controller.
  9. Return viewController in makeUIViewController function.
  10. In updateUIViewController method, get the native ad view from NativeAdCoordinator class, and add to the view controller as shown below:


struct NativeView: UIViewControllerRepresentable {
    class NativeAdViewController: UIViewController {}
    
    typealias UIViewControllerType = NativeAdViewController
    @ObservedObject var nativeAdCoordinator: NativeAdCoordinator
    
    
    func makeUIViewController(context: Context) -> NativeAdViewController {
        let viewController = NativeAdViewController()
        nativeAdCoordinator.viewController = viewController
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: NativeAdViewController, context: Context) {
        var nativeAd: NativeAdView? = nil
        do {
            nativeAd = try nativeAdCoordinator.nativeAd?.getAdView() as? NativeAdView
        } catch {
            print("error: \(error.localizedDescription)")
            return
        }
        guard let nativeAd = nativeAd else {
            return
        }
        uiViewController.view.subviews.forEach({$0.removeFromSuperview()})
        uiViewController.view.addSubview(nativeAd)
        nativeAd.frame = uiViewController.view.frame
    }
}


Implement NativeAdCoordinator

  1. In NativeAdCoordinator class, create @Published MesonNative object to reflect any changes made to the native ad view.
  2. Create object for MesonNative type.
  3. Create object for UIViewController.
  4. Implement loadAd method to initialize the native object, add template class, and load the ad.
  5. Implement the MesonNativeDelegate methods.
  6. In mesonNativeDidLoad, assign mesonNative to the published native object to notify the view that the native ad is loaded and ready to view.
 class NativeAdCoordinator: NSObject, ObservableObject, MesonNativeDelegate {
    @Published var native: MesonNative?
    var nativeAd: MesonNative?
    var viewController: UIViewController = UIViewController()
    
    func viewControllerForMesonFullScreen() -> UIViewController {
        viewController
    }
    
    func loadAd() {
        nativeAd = MesonNative(adUnitId: "YOUR-NATIVE-ADUNIT-ID", delegate: self)
        nativeAd?.adTemplateViewClass = NativeAdView.self
        nativeAd?.load()
    }

    func mesonNativeDidLoad(_ mesonNative: MesonNative) {
        self.native = mesonNative
        print("\(#function)")
    }
    func mesonNativeDidLoadFail(_ mesonNative: MesonNative, error: Error) {
        print("\(#function)")
    }
    func mesonNativeDidClick(_ mesonNative: MesonNative, params: [String : Any]?) {
        print("\(#function)")
    }
    func mesonNativeImpression(_ mesonNative: MesonNative, adData: MesonAdData?) {
        print("\(#function)")
    }
    func mesonNativeWillPresentScreen(_ mesonNative: MesonNative) {
        print("\(#function)")
    }
    func mesonNativeDidPresentScreen(_ mesonNative: MesonNative) {
        print("\(#function)")
    }
    func mesonNativeWillCollapseScreen(_ mesonNative: MesonNative) {
        print("\(#function)")
    }
    func mesonNativeDidCollapseScreen(_ mesonNative: MesonNative) {
        print("\(#function)")
    }
    func mesonNativeUserWillLeaveApplication(_ mesonNative: MesonNative) {
        print("\(#function)")
    }
}

Add Native Ad to View Hierarchy

  1. Inside view, create a private State object for NativeAdCoordinator class.
  2. In your view hierarchy, add NativeView(nativeAdCoordinator:) with the desired frame.
  3. Call the coordinator.loadAd() method to load and show the native ad.

import SwiftUI
import MesonSDK

struct NativeContentView: View {
    @State private var coordinator = NativeAdCoordinator()

    let navigationTitle: String
    
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                NativeView(nativeAdCoordinator: coordinator)
                    .frame(height: 400)
                
                Button("Refresh Ad") {
                    coordinator.loadAd()
                }
            }
            .padding()
        }
        .onAppear {
            coordinator.loadAd()
        }
    }
}