'How to detect if code is running in Main App or App Extension Target?
Does anyone know how you detect from within your code if you're running inside an App Extension?
I have an app which shares classes between an app and an extension. The app code uses [UIApplication sharedApplication]
but this isn't available from within an extension, so it won't compile saying:
'sharedApplication' is unavailable: not available iOS (App Extension)
So I need a way to detect that I'm in the extension and use an alternative to sharedApplication
if that's the case.
Solution 1:[1]
You can use a preprocessor macro:
In the project settings use the dropdown in the topbar to select your extension target:
Then:
- Click
Build Settings
- Find (or search)
Preprocessor Macros
underApple LLVM 6.0 - Preprocessing
- Add
TARGET_IS_EXTENSION
or any other name of your choice in both the debug and release sections.
Then in your code:
#ifndef TARGET_IS_EXTENSION // if it's not defined
// Do your calls to UIApplication
#endif
Solution 2:[2]
As Apple's documentation says:
When you build an extension based on an Xcode template, you get an extension bundle that ends in .appex.
So, we can use the following code:
if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) {
// this is an app extension
}
// Swift version
if Bundle.main.bundlePath.hasSuffix(".appex") {
// this is an app extension
}
Solution 3:[3]
The preprocessor macro will work mostly, but will not work in shared library (e.g. cocoapods or shared frameworks).
Alternatively you can use following code.
@implementation ExtensionHelpers
+(BOOL) isAppExtension
{
return [[[NSBundle mainBundle] executablePath] containsString:@".appex/"];
}
@end
This work by checking the bundle executablePath, as only App Extension has extension ".appex".
Solution 4:[4]
Swift 5
let bundleUrl: URL = Bundle.main.bundleURL
let bundlePathExtension: String = bundleUrl.pathExtension
let isAppex: Bool = bundlePathExtension == "appex"
// `true` when invoked inside the `Extension process`
// `false` when invoked inside the `Main process`
Solution 5:[5]
The solution proposed by @Andrew did not work for me.
What worked was:
- Select extension target
- Build Settings
- Search "Custom Flags"
- Add a new Flag (example: "EXTENSION") to Debug and Release
Now the code:
#if EXTENSION
// IF is extension (SIRI) we do stuff
#else
// ELSE is main app do more stuff
#endif
Solution 6:[6]
You can add a preprocessor macro on the extension target and then check with a #ifdef
inside of your class.
Solution 7:[7]
For my shared library I created a separate target who's app extensions flag is set to yes, and used preprocessor macro's within the build settings for that specific target.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | some_id |
Solution 3 | siuying |
Solution 4 | neoneye |
Solution 5 | |
Solution 6 | Marcelo Fabri |
Solution 7 | cohen72 |