如何检测代码是否在主应用程序或应用程序扩展目标中运行?

Mar*_*ges 32 uiapplicationdelegate ios ios-app-extension

如果您在App扩展程序内运行,是否有人知道您如何从代码中检测到?

我有一个应用程序,它在应用程序和扩展程序之间共享类.应用程序代码使用,[UIApplication sharedApplication]但这不能从扩展中获得,因此它不会编译说:

'sharedApplication'不可用:iOS(App Extension)不可用

因此,我需要一种方法来检测我是否在扩展中并使用替代方案,sharedApplication如果是这种情况.

San*_*aus 48

您可以使用预处理器宏:

在项目设置中,使用顶部栏中的下拉列表选择您的扩展目标: 在此输入图像描述

然后:

  1. 点击 Build Settings
  2. 查找(或搜索)Preprocessor MacrosApple LLVM 6.0 - Preprocessing
  3. TARGET_IS_EXTENSION在调试和发布部分中添加或您选择的任何其他名称.

然后在你的代码中:

#ifndef TARGET_IS_EXTENSION // if it's not defined
    // Do your calls to UIApplication
#endif
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案不适用于框架中的代码.我们目前检查应用程序包的名称,以查看代码是否在扩展中运行,但我希望找到更好的方法. (11认同)

Rus*_*orb 28

正如Apple的文档所说:

当您基于Xcode模板构建扩展时,您将获得以.appex结尾的扩展束.

所以,我们可以使用以下代码:

if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) {
    // this is an app extension
}
Run Code Online (Sandbox Code Playgroud)

  • 不是很干净,它是间接的,如果扩展发生变化,将来可能会发生变化,加上条件编译将允许您排除无法在扩展中编译的资源或方法。 (4认同)
  • upvote参考文档 - 干得好 (3认同)
  • 但它不会解决编译问题. (3认同)

小智 23

预处理器宏将主要工作,但不能在共享库中工作(例如cocoapods或共享框架).

或者,您可以使用以下代码.

@implementation ExtensionHelpers

+(BOOL) isAppExtension
{
    return [[[NSBundle mainBundle] executablePath] containsString:@".appex/"];
}

@end
Run Code Online (Sandbox Code Playgroud)

这项工作通过检查bundle executablePath,因为只有App Extension具有扩展名".appex".

  • 编译共享库时,我仍然遇到编译错误,因为它具有"仅需要应用程序扩展安全API"的标志设置为YES.如何在使用上面编写的代码时如何避免编译错误? (12认同)

Tia*_*des 11

@Andrew 提出的解决方案对我不起作用。

有效的是:

  1. 选择扩展目标
  2. 构建设置
  3. 搜索“自定义标志”
  4. 添加新标志(例如:“EXTENSION”)以调试和发布

在此输入图像描述

现在的代码:

#if EXTENSION
// IF is extension (SIRI) we do stuff
#else
// ELSE is main app do more stuff
#endif
Run Code Online (Sandbox Code Playgroud)


neo*_*eye 9

斯威夫特 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`
Run Code Online (Sandbox Code Playgroud)