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.