From 2c8f5abd5f3e4e42b54b6317b32cd8bf07abf2b2 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 6 Mar 2017 15:34:58 -0500 Subject: [PATCH] Remove direct use of UIApplication from GTMSessionFetcher. iOS application extensions don't play well with +[UIApplication sharedApplication], and attempting to compile the symbol gets a compile error. We previously used GTM_BACKGROUND_UIAPPLICATION to gate access, but that doesn't work when building shared frameworks to use with both the app and an extension. This removes the GTM_BACKGROUND_UIAPPLICATION define altogether. It does leave GTM_BACKGROUND_TASK_FETCHING, in case clients want to compile out the background task behavior altogether. --- Source/GTMSessionFetcher.h | 7 ------- Source/GTMSessionFetcher.m | 26 +++++++++++++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) 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