From 654cdca5d6d21ef7a4f7c95b0c5ececc33c63fdb Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 13:59:50 +0000 Subject: [PATCH 1/3] Fix iOS 13.0 keyWindow deprecation warning - Add UIApplication extension with keyRootViewController property - Replace deprecated keyWindow calls with keyRootViewController - Fixes #6 Co-authored-by: leesam <2sem@users.noreply.github.com> --- GADManager/GADManager.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/GADManager/GADManager.swift b/GADManager/GADManager.swift index a7ef34c..c7f3e20 100644 --- a/GADManager/GADManager.swift +++ b/GADManager/GADManager.swift @@ -11,6 +11,14 @@ import GoogleMobileAds import AdSupport import AppTrackingTransparency +extension UIApplication { + var keyRootViewController: UIViewController? { + guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return nil } + + return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController + } +} + public protocol GADManagerDelegate : NSObjectProtocol{ //associatedtype E : RawRepresentable where E.RawValue == String func GAD(manager: GADManager, lastPreparedTimeForUnit unit: E) -> Date; @@ -452,11 +460,11 @@ public class GADManager : NSObject, GoogleMobileAds.FullSc }*/ //ignore if alert is being presented - /*if let alert = UIApplication.shared.keyWindow?.rootViewController?.presentedViewController as? UIAlertController{ + /*if let alert = UIApplication.shared.keyRootViewController?.presentedViewController as? UIAlertController{ alert.dismiss(animated: false, completion: nil); }*/ - guard !(UIApplication.shared.keyWindow?.rootViewController?.presentedViewController is UIAlertController) else{ + guard !(UIApplication.shared.keyRootViewController?.presentedViewController is UIAlertController) else{ //alert.dismiss(animated: false, completion: nil); //self.fullAd = nil; completion?(unit, self.adObjects[unit], false); From a9320799b60d6d87c882d754d89f37cf9a5aa016 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 14:36:30 +0000 Subject: [PATCH 2/3] Improve multi-scene handling with foregroundActive selection - Added foregroundActive scene selection logic for better multi-scene app support - Added fallback to any connected scene if no foreground active scene exists - Changed extension access level to private to avoid namespace pollution - Added comprehensive documentation comments Co-authored-by: leesam <2sem@users.noreply.github.com> --- GADManager/GADManager.swift | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/GADManager/GADManager.swift b/GADManager/GADManager.swift index c7f3e20..8d9862d 100644 --- a/GADManager/GADManager.swift +++ b/GADManager/GADManager.swift @@ -11,9 +11,24 @@ import GoogleMobileAds import AdSupport import AppTrackingTransparency -extension UIApplication { +/// Private extension to safely access the root view controller in iOS 13+ scene-based apps +private extension UIApplication { + /// Returns the root view controller of the key window in the active scene. + /// For multi-scene apps, prioritizes the foreground active scene with fallback logic. + /// - Returns: The root view controller, or nil if no valid scene/window is found. var keyRootViewController: UIViewController? { - guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return nil } + // First, try to get the foreground active scene (ideal for multi-scene apps) + if let windowScene = UIApplication.shared.connectedScenes + .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { + return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController + } + + // Fallback: try any connected scene if no foreground active scene is available + guard let windowScene = UIApplication.shared.connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .first else { + return nil + } return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController } From 5e965863c2302c3652e2319e0ed681f77b933ffe Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 14:51:34 +0000 Subject: [PATCH 3/3] Refactor: Move keyRootViewController to UIApplication+.swift - Moved private extension from GADManager.swift to UIApplication+.swift - Fixed UIApplication.shared to use self within extension - Improves code organization by consolidating UIApplication extensions Co-authored-by: leesam <2sem@users.noreply.github.com> --- GADManager/GADManager.swift | 23 ------------------ GADManager/extensions/UIApplication+.swift | 27 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/GADManager/GADManager.swift b/GADManager/GADManager.swift index 8d9862d..9549fe7 100644 --- a/GADManager/GADManager.swift +++ b/GADManager/GADManager.swift @@ -11,29 +11,6 @@ import GoogleMobileAds import AdSupport import AppTrackingTransparency -/// Private extension to safely access the root view controller in iOS 13+ scene-based apps -private extension UIApplication { - /// Returns the root view controller of the key window in the active scene. - /// For multi-scene apps, prioritizes the foreground active scene with fallback logic. - /// - Returns: The root view controller, or nil if no valid scene/window is found. - var keyRootViewController: UIViewController? { - // First, try to get the foreground active scene (ideal for multi-scene apps) - if let windowScene = UIApplication.shared.connectedScenes - .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { - return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController - } - - // Fallback: try any connected scene if no foreground active scene is available - guard let windowScene = UIApplication.shared.connectedScenes - .compactMap({ $0 as? UIWindowScene }) - .first else { - return nil - } - - return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController - } -} - public protocol GADManagerDelegate : NSObjectProtocol{ //associatedtype E : RawRepresentable where E.RawValue == String func GAD(manager: GADManager, lastPreparedTimeForUnit unit: E) -> Date; diff --git a/GADManager/extensions/UIApplication+.swift b/GADManager/extensions/UIApplication+.swift index 31138c6..83bfc15 100644 --- a/GADManager/extensions/UIApplication+.swift +++ b/GADManager/extensions/UIApplication+.swift @@ -17,7 +17,7 @@ import UIKit extension UIApplication{ - + /** os compatible for function to open url */ @@ -28,7 +28,7 @@ extension UIApplication{ self.openURL(url); } } - + /** Opens Settings App page for this app - parameter completion: block to call after opening Settings App has been completed @@ -38,3 +38,26 @@ extension UIApplication{ self.openCompatible(url_settings!, options: [:], completionHandler: completion) } } + +/// Private extension to safely access the root view controller in iOS 13+ scene-based apps +private extension UIApplication { + /// Returns the root view controller of the key window in the active scene. + /// For multi-scene apps, prioritizes the foreground active scene with fallback logic. + /// - Returns: The root view controller, or nil if no valid scene/window is found. + var keyRootViewController: UIViewController? { + // First, try to get the foreground active scene (ideal for multi-scene apps) + if let windowScene = self.connectedScenes + .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { + return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController + } + + // Fallback: try any connected scene if no foreground active scene is available + guard let windowScene = self.connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .first else { + return nil + } + + return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController + } +}