From 8fbfe5ed6dee45cf57cdd619a08d2f8fbdbc9d85 Mon Sep 17 00:00:00 2001 From: John Rosendahl Date: Fri, 30 Oct 2026 14:28:53 -0600 Subject: [PATCH] Load demo banners on the main thread The Swift GAM and Prebid demos loaded their banners from the targeting completion handler, which the SDK calls on a background thread. Hop to the main thread before loading, and again after Prebid's fetchDemand, as the usage guide does. Co-Authored-By: Claude Opus 5.5 --- .../GAMBannerViewController.swift | 19 ++++++++------- .../PrebidBannerViewController.swift | 23 +++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/demo-ios-swift/demo-ios-swift/GAMBannerViewController.swift b/demo-ios-swift/demo-ios-swift/GAMBannerViewController.swift index b20692d..64f545a 100644 --- a/demo-ios-swift/demo-ios-swift/GAMBannerViewController.swift +++ b/demo-ios-swift/demo-ios-swift/GAMBannerViewController.swift @@ -54,14 +54,17 @@ final class GAMBannerViewController: UIViewController { @IBAction func loadBannerWithTargeting(_ sender: UIButton) { do { try OPTABLE!.targeting { [weak self] result in - switch result { - case let .success(optableTargeting): - print("[OptableSDK] ✅ Success on /targeting API call: \(optableTargeting)") - self?.loadBanner(optableTargeting) - - case let .failure(error): - print("[OptableSDK] 🚫 Error on /targeting API call: \(error)") - self?.loadBanner() + // The completion handler is not called on the main thread, and ads must be loaded on it. + DispatchQueue.main.async { + switch result { + case let .success(optableTargeting): + print("[OptableSDK] ✅ Success on /targeting API call: \(optableTargeting)") + self?.loadBanner(optableTargeting) + + case let .failure(error): + print("[OptableSDK] 🚫 Error on /targeting API call: \(error)") + self?.loadBanner() + } } } } catch { diff --git a/demo-ios-swift/demo-ios-swift/PrebidBannerViewController.swift b/demo-ios-swift/demo-ios-swift/PrebidBannerViewController.swift index 83b6e24..1e3ab48 100644 --- a/demo-ios-swift/demo-ios-swift/PrebidBannerViewController.swift +++ b/demo-ios-swift/demo-ios-swift/PrebidBannerViewController.swift @@ -58,14 +58,17 @@ final class PrebidBannerViewController: UIViewController { // Outlets @IBAction func loadBannerWithTargeting(_ sender: UIButton) { do { try OPTABLE!.targeting { [weak self] result in - switch result { - case let .success(optableTargeting): - print("[OptableSDK] ✅ Success on /targeting API call: \(optableTargeting)") - self?.loadBanner(optableTargeting) - - case let .failure(error): - print("[OptableSDK] 🚫 Error on /targeting API call: \(error)") - self?.loadBanner() + // The completion handler is not called on the main thread, and ads must be loaded on it. + DispatchQueue.main.async { + switch result { + case let .success(optableTargeting): + print("[OptableSDK] ✅ Success on /targeting API call: \(optableTargeting)") + self?.loadBanner(optableTargeting) + + case let .failure(error): + print("[OptableSDK] 🚫 Error on /targeting API call: \(error)") + self?.loadBanner() + } } } } catch { @@ -107,7 +110,9 @@ private extension PrebidBannerViewController { pbmBannerAdUnit = BannerAdUnit(configId: PREBID_STORED_IMP, size: .init(width: 320, height: 50)) pbmBannerAdUnit.fetchDemand(adObject: adRequest) { [weak self] status in print("[PrebidMobile]:fetchDemand(adObject:): \(status.name())") - self?.loadGAMAd(adRequest) + DispatchQueue.main.async { + self?.loadGAMAd(adRequest) + } } }