รองรับหลายหน้าต่างและอุปกรณ์แบบพับได้

แอปพลิเคชันที่รองรับหลายหน้าต่างบน iPad หรือทำงานบนอุปกรณ์แบบพับได้ เช่น iPhone Duo สามารถแสดง UI ในหน้าต่างขนาดต่างๆ และการกำหนดค่าหน้าจอแบบไดนามิกได้ ใน iPad ผู้ใช้สามารถโต้ตอบกับสำเนา UI ของแอปหลายรายการพร้อมกันและปรับขนาดหน้าต่างได้ ในอุปกรณ์แบบพับได้ สถานะการพับของอุปกรณ์จะเป็นตัวกำหนดหน้าจอที่ใช้งานอยู่ เมื่อกางออก อุปกรณ์จะใช้จอแสดงผลด้านในที่ใหญ่ขึ้น เมื่อพับ อุปกรณ์จะใช้จอแสดงผลด้านนอกที่มีขนาดเล็กกว่า

คู่มือนี้ครอบคลุมการโหลดและการแสดงโฆษณาในสภาพแวดล้อมแบบหลายหน้าต่างและจอแสดงผลแบบพับได้

ข้อกำหนดเบื้องต้น

ก่อนเริ่มต้น ให้ทำตามขั้นตอนต่อไปนี้

ตั้งค่าฉากหน้าต่างในคำขอโฆษณา

หากต้องการรับโฆษณาที่พอดีกับหน้าต่างหรือจอแสดงผลที่ใช้งานอยู่ ให้กำหนดออบเจ็กต์ 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)")
  }
}

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 ได้มากกว่า 1 ครั้งในวงจรของแอป แต่คุณต้องรวมคำขอโฆษณาไว้ในแฟล็กบูลีนเพื่อให้ทำงานเพียงครั้งเดียว

ตัวอย่างต่อไปนี้จะเริ่มต้นคำขอโฆษณาในเมธอด 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];
  });
}

โฆษณาเนทีฟ

คุณควบคุมเลย์เอาต์ของโฆษณาเนทีฟได้ คุณไม่จำเป็นต้องโหลดโฆษณาเนทีฟซ้ำเมื่อหน้าต่างปรับขนาด ซึ่งแตกต่างจากแบนเนอร์หรือโฆษณาแบบเต็มหน้าจอ ใช้ข้อจำกัดของ Auto Layout มาตรฐานหรือเลย์เอาต์ SwiftUI สำหรับมุมมองโฆษณาเนทีฟเพื่อปรับให้เข้ากับการเปลี่ยนแปลงขนาด