پشتیبانی از چند پنجره و دستگاه تاشو

برنامه‌هایی که از چندین پنجره در iPad پشتیبانی می‌کنند یا در دستگاه‌های تاشو، مانند iPhone Duo، اجرا می‌شوند، می‌توانند واسط کاربر را در اندازه‌های پنجره پویا و پیکربندی‌های صفحه نمایش دهند. در iPad، کاربران می‌توانند با چندین نسخه هم‌زمان از میانای کاربر برنامه تعامل داشته باشند و اندازه پنجره‌ها را تغییر دهند. در دستگاه‌های تاشو، وضعیت تاشدن دستگاه تعیین‌کننده صفحه‌نمایش فعال است. وقتی دستگاه باز می‌شود، از نمایشگر داخلی بزرگ‌تر استفاده می‌کند. وقتی دستگاه تا شده باشد، از نمایشگر بیرونی کوچک‌تر استفاده می‌کند.

این راهنما بار کردن و ارائه آگهی‌ها را در محیط‌های چندپنجره‌ای و نمایشگرهای تاشو پوشش می‌دهد.

پیش‌نیازها

قبل‌از شروع، موارد زیر را تکمیل کنید:

تنظیم صحنه پنجره در درخواست آگهی

برای دریافت آگهی‌ای که با پنجره‌ای خاص یا نمایشگر فعال مطابقت داشته باشد، شیء فعال UIWindowScene را به ویژگی scene در شیء GADRequest اختصاص دهید. ‫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)")
  }
}

آبجکتیو-سی

- (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
  }
}

آبجکتیو-سی

- (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()
      }
    }
  }
}

آبجکتیو-سی

- (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)
    }
  }
}

آبجکتیو-سی

- (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];
  });
}

آگهی‌های بومی

شما چیدمان آگهی‌های بومی را کنترل می‌کنید. برخلاف برنماها یا آگهی‌های تمام‌صفحه، هنگام تغییر اندازه پنجره نیازی به بار کردن مجدد آگهی‌های بومی ندارید. از محدودیت‌های Auto Layout استاندارد یا چیدمان‌های SwiftUI برای نمای آگهی بومی استفاده کنید تا با تغییرات اندازه سازگار شود.