支援多視窗和摺疊式裝置

如果應用程式支援 iPad 的多視窗模式,或可在 iPhone Duo 等摺疊式裝置上執行,就能在動態視窗大小和螢幕設定中顯示 UI。在 iPad 上,使用者可以同時與應用程式 UI 的多個副本互動,並調整視窗大小。在摺疊式裝置上,裝置的摺疊狀態會決定使用中的螢幕。展開時,裝置會使用較大的內螢幕。摺疊時,裝置會使用較小的外螢幕。

本指南說明如何在多視窗模式環境和摺疊式螢幕中載入及顯示廣告。

必要條件

開始前,請先完成下列事項:

在廣告請求中設定視窗場景

如要接收符合特定視窗或有效顯示區塊的廣告,請將有效的 UIWindowScene 物件指派給 GADRequest 物件的 scene 屬性。Google Mobile Ads SDK 會傳回適合該場景大小的廣告。在 SwiftUI 中,查詢已連結的場景,找出有效的前景視窗場景。

以下範例會設定視窗場景,在成功時載入插頁式廣告,失敗時則記錄錯誤訊息:

Swift

func loadInterstitial() async {
  let request = Request()
  request.scene = view.window?.windowScene

  do {
    interstitial = try await InterstitialAd.load(
      with: "ca-app-pub-3940256099942544/4411468910", request: request)
  } catch {
    print("Failed to load interstitial ad with error: \(error.localizedDescription)")
  }
}

SwiftUI

func loadInterstitial() async {
  let request = Request()
  request.scene =
    UIApplication.shared.connectedScenes
    .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene

  do {
    let _ = try await InterstitialAd.load(
      with: "ca-app-pub-3940256099942544/4411468910", request: request)
  } catch {
    print("Failed to load interstitial ad with error: \(error.localizedDescription)")
  }
}

Objective-C

- (void)loadInterstitial {
  GADRequest *request = [GADRequest request];
  request.scene = self.view.window.windowScene;

  [GADInterstitialAd
       loadWithAdUnitID:@"ca-app-pub-3940256099942544/4411468910"
                request:request
      completionHandler:^(GADInterstitialAd *ad, NSError *error) {
        if (error) {
          NSLog(@"Failed to load interstitial ad with error: %@", [error localizedDescription]);
          return;
        }
        self.interstitial = ad;
      }];
}

在測試模式下,如果多場景應用程式在請求廣告時未傳遞場景,廣告請求會失敗,並顯示下列錯誤:

<Google> Invalid Request. The GADRequest scene property should be set for
applications that support multi-scene. Treating the unset property as an error
while in test mode.

在正式環境模式中,廣告請求會供應廣告,但如果廣告顯示在小於廣告素材大小的視窗中,則無法顯示廣告:

<Google> Ad cannot be presented. The full screen ad content size exceeds the current window size.

建立廣告請求

傳送廣告請求時,多場景應用程式需要有效的視窗場景。 在視窗場景填入內容的位置,使用 viewDidAppear 方法建立廣告請求。我們建議採用這項程序,因為在 viewDidLoad 方法中,檢視畫面尚未新增至視窗。

雖然您可以在應用程式生命週期中多次呼叫 viewDidAppear 方法,但必須將廣告請求包裝在布林值旗標中,才能只執行一次。

以下範例會在 viewDidAppear 方法中初始化廣告請求:

Swift

override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)
  if !requestInitialized {
    Task {
      await loadInterstitial()
    }
    requestInitialized = true
  }
}

Objective-C

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  if (!_requestInitialized) {
    [self loadInterstitial];
    _requestInitialized = YES;
  }
}

處理視窗大小調整

當使用者在 iPad 上調整場景大小,或摺疊/展開 iPhone Duo 等摺疊式裝置時,視窗尺寸就會改變。視窗大小變更時,請確認載入的廣告符合更新後的尺寸,並視需要重新載入廣告。

如要確認載入的廣告符合更新後的尺寸,請使用下列任一方法:

全螢幕廣告

如要確認載入的全螢幕廣告是否仍適用於更新後的視窗大小或折疊狀態,請使用 canPresentFromRootViewController:error: 方法。如果檢查失敗,請載入符合更新後場景大小的廣告。

以下範例會檢查插頁式廣告是否能在大小轉換後顯示,並視需要重新載入廣告:

Swift

override func viewWillTransition(
  to size: CGSize,
  with coordinator: UIViewControllerTransitionCoordinator
) {
  super.viewWillTransition(to: size, with: coordinator)

  coordinator.animate(alongsideTransition: nil) { [weak self] _ in
    guard let self else { return }
    do {
      try self.interstitial?.canPresent(from: self)
    } catch {
      Task {
        await self.loadInterstitial()
      }
    }
  }
}

Objective-C

- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

  [coordinator
      animateAlongsideTransition:nil
                      completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
                        if (![self.interstitial canPresentFromRootViewController:self error:nil]) {
                          [self loadInterstitial];
                        }
                      }];
}

處理視窗大小調整和摺疊轉換,類似於裝置旋轉。將橫幅廣告檢視畫面限制在 safeAreaLayoutGuide 屬性。這樣一來,廣告就不會遮住裝置轉軸、凹口和系統資訊列。這個程序也會使用更新後的安全區域寬度,重新計算錨定自動調整橫幅廣告大小。

以下範例會在大小轉換期間,載入視窗寬度更新後的錨定自動調整橫幅廣告:

Swift

override func viewWillTransition(
  to size: CGSize,
  with coordinator: UIViewControllerTransitionCoordinator
) {
  super.viewWillTransition(to: size, with: coordinator)

  coordinator.animate(alongsideTransition: nil) { [weak self] _ in
    self?.loadBannerAd()
  }
}

@MainActor
func loadBannerAd() {
  let frame = view.frame.inset(by: view.safeAreaInsets)
  let viewWidth = frame.size.width

  bannerView.adSize = largeAnchoredAdaptiveBanner(width: viewWidth)

  let request = Request()
  request.scene = view.window?.windowScene
  bannerView.load(request)
}

SwiftUI

struct MultiSceneBannerView: View {
  var body: some View {
    GeometryReader { geometry in
      let adSize = largeAnchoredAdaptiveBanner(width: geometry.size.width)
      MultiSceneBannerViewContainer(adSize: adSize)
        .frame(width: adSize.size.width, height: adSize.size.height)
    }
  }
}

private struct MultiSceneBannerViewContainer: UIViewRepresentable {
  let adSize: AdSize

  func makeUIView(context: Context) -> BannerView {
    let bannerView = BannerView(adSize: adSize)
    let request = Request()
    request.scene =
      UIApplication.shared.connectedScenes
      .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
    bannerView.load(request)
    return bannerView
  }

  func updateUIView(_ uiView: BannerView, context: Context) {
    if uiView.adSize.size != adSize.size {
      uiView.adSize = adSize
      let request = Request()
      request.scene = uiView.window?.windowScene
      uiView.load(request)
    }
  }
}

Objective-C

- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

  [coordinator
      animateAlongsideTransition:nil
                      completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
                        [self loadBannerAd];
                      }];
}

- (void)loadBannerAd {
  dispatch_async(dispatch_get_main_queue(), ^{
    CGRect frame = UIEdgeInsetsInsetRect(self.view.frame, self.view.safeAreaInsets);
    CGFloat viewWidth = frame.size.width;

    self.bannerView.adSize = GADLargeAnchoredAdaptiveBannerAdSizeWithWidth(viewWidth);

    GADRequest *request = [GADRequest request];
    request.scene = self.view.window.windowScene;
    [self.bannerView loadRequest:request];
  });
}

原生廣告

您可以控制原生廣告的版面配置。與橫幅或全螢幕廣告不同,原生廣告在視窗大小調整時不需要重新載入。請使用標準自動版面配置限制或 SwiftUI 版面配置,讓原生廣告檢視區塊配合大小變化調整。