diff --git a/Source/GTMSessionFetcher.h b/Source/GTMSessionFetcher.h index bfba1479..a649cf0e 100644 --- a/Source/GTMSessionFetcher.h +++ b/Source/GTMSessionFetcher.h @@ -382,13 +382,6 @@ #define GTM_BACKGROUND_TASK_FETCHING 1 #endif -// If GTM_BACKGROUND_TASK_FETCHING is enabled and GTMUIApplicationProtocol is not used, -// GTM_BACKGROUND_UIAPPLICATION will allow defaulting to UIApplication. To avoid references to -// UIApplication (e.g. for extensions), set GTM_BACKGROUND_UIAPPLICATION to 0. -#if TARGET_OS_IPHONE && !TARGET_OS_WATCH && !defined(GTM_BACKGROUND_UIAPPLICATION) - #define GTM_BACKGROUND_UIAPPLICATION 1 -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/Source/GTMSessionFetcher.m b/Source/GTMSessionFetcher.m index 4c9327d8..e3f52d87 100644 --- a/Source/GTMSessionFetcher.m +++ b/Source/GTMSessionFetcher.m @@ -1977,13 +1977,25 @@ + (void)setSubstituteUIApplication:(nullable id)app { id app = gSubstituteUIApp; if (app) return app; - // Some projects use GTM_BACKGROUND_UIAPPLICATION to avoid compile-time references - // to UIApplication. -#if GTM_BACKGROUND_UIAPPLICATION - return (id) [UIApplication sharedApplication]; -#else - return nil; -#endif + // iOS App extensions should not call [UIApplication sharedApplication], even + // if UIApplication responds to it. + + static Class applicationClass = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + BOOL isAppExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + if (!isAppExtension) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + }); + + if (applicationClass) { + app = (id)[applicationClass sharedApplication]; + } + return app; } #endif // TARGET_OS_IPHONE