Google AdMob Smart Banner in SwiftUI for both orientations

Viewed 402

I want to add a smart banner adView (meaning ad spans to full app width) into my app, which works in both orientations. I've found few code snippets for a standard fixed-size banner, but not for smart banner, especially working for both orientations (which ofc can change at runtime).

I've made my own solution, it works in test-mode, but in production-mode some banners are truncated (most are fine):

import GoogleMobileAds
import SwiftUI
import UIKit

struct GADBannerViewController: UIViewControllerRepresentable {
    
    @State var isPortrait: Bool
    
    func makeUIViewController(context: Context) -> UIViewController {
        let bannerView = GADBannerView(adSize: Utils.adSize())
        let viewController = UIViewController()
        bannerView.adUnitID = AppData.ADMOB_BANNER_ID
        bannerView.rootViewController = viewController
        viewController.view.addSubview(bannerView)
        updateVCFrame(view: viewController.view)
        let request = GADRequest()
        bannerView.load(request)
        bannerView.tag = 999
        return viewController
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        updateVCFrame(view: uiViewController.view)
        if let view = uiViewController.view.subviews.first(where: { $0.tag == 999 } ), let bannerView = view as? GADBannerView {
            bannerView.adSize = Utils.adSize()
        }
    }
    
    func updateVCFrame(view: UIView) {
        view.frame = CGRect(origin: .zero, size: GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(view.frame.width).size)
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(isPortrait: $isPortrait)
    }
    
    class Coordinator: NSObject {
        @Binding var isPortrait: Bool
        
        init(isPortrait: Binding<Bool>) {
            _isPortrait = isPortrait
        }
    }
}

struct BannerView: View {
    static let BANNER_HEIGHT: CGFloat = UIDevice.current.userInterfaceIdiom == .pad ? 90 : 50
    
    @State var isPortrait: Bool = true
    
    var body: some View {
        GADBannerViewController(isPortrait: isPortrait)
            .frame(maxWidth: .infinity)
            .frame(height: BannerView.BANNER_HEIGHT)
            .onReceive(NotificationCenter.Publisher(center: .default, name: UIDevice.orientationDidChangeNotification)) { _ in
                isPortrait = Utils.isPortrait() //triggers updateUIViewController 
            }
    }
}

struct BannerView_Previews: PreviewProvider {
    static var previews: some View {
        BannerView()
    }
}

class Utils {
    
    public static func isPortrait() -> Bool {
        let boundsLandscape = UIScreen.main.bounds.width > UIScreen.main.bounds.height
        switch UIDevice.current.orientation {
        case .portrait:
            return true
        case .portraitUpsideDown:
            return true
        case .landscapeLeft:
            return false
        case .landscapeRight:
            return false
        default:
            break
        }
        return !boundsLandscape
    }
    
    public static func adSize() -> GADAdSize {
//        return kGADAdSizeFluid //not working!
        let boundsLandscape = UIScreen.main.bounds.width > UIScreen.main.bounds.height
        switch UIDevice.current.orientation{
        case .portrait:
            return kGADAdSizeSmartBannerPortrait
        case .portraitUpsideDown:
            return kGADAdSizeSmartBannerPortrait
        case .landscapeLeft:
            return kGADAdSizeSmartBannerLandscape
        case .landscapeRight:
            return kGADAdSizeSmartBannerLandscape
        default:
            break
        }
        return boundsLandscape ? kGADAdSizeSmartBannerLandscape : kGADAdSizeSmartBannerPortrait
    }
    
}

GADBannerView is nested in GADBannerViewController, which is nested in BannerView. BANNER_HEIGHT is hardcoded 50 for iPhone and 90 for iPad.

Can I make this simpler and fix truncating issue? I haven't found and "pro" or official solution.

0 Answers
Related