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

问题描述 投票:0回答:8

有谁知道如何从代码中检测您是否在应用程序扩展中运行?

我有一个在应用程序和扩展程序之间共享类的应用程序。应用程序代码使用

[UIApplication sharedApplication]
但这在扩展中不可用,因此它不会编译:

“sharedApplication”不可用:不可用 iOS(应用程序扩展)

所以我需要一种方法来检测我是否在扩展中,并使用

sharedApplication
的替代方案(如果是这种情况)。

ios uiapplicationdelegate ios-app-extension
8个回答
58
投票

您可以使用预处理器宏:

在项目设置中,使用顶部栏中的下拉菜单选择您的扩展目标: enter image description here

然后:

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

然后在你的代码中:

#ifndef TARGET_IS_EXTENSION // if it's not defined
    // Do your calls to UIApplication
#endif

50
投票

正如 Apple 的文档 所说:

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

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

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

// Swift version
if Bundle.main.bundlePath.hasSuffix(".appex") {
    // this is an app extension
}

23
投票

预处理器宏大部分情况下都可以工作,但在共享库(例如cocoapods或共享框架)中不起作用。

您也可以使用以下代码。

@implementation ExtensionHelpers

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

@end

此工作通过检查捆绑包可执行路径来完成,因为只有应用程序扩展具有扩展名“.appex”。


12
投票

斯威夫特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`

11
投票

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

有效的是:

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

enter image description here

现在是代码:

#if EXTENSION
// IF is extension (SIRI) we do stuff
#else
// ELSE is main app do more stuff
#endif

3
投票

您可以在扩展目标上添加预处理器宏,然后使用类内部的

#ifdef
进行检查。


0
投票

对于我的共享库,我创建了一个单独的目标,其应用程序扩展标志设置为 yes,并在该特定目标的构建设置中使用了预处理器宏。


0
投票

在开发框架(例如 Swift Package)时,使用预处理器宏提供的答案仍然不能很好地工作。

相反,您可以将属性

@available(iOSApplicationExtension, unavailable)
用于需要调用
UIApplication.shared
的方法,然后安全地调用
shared

© www.soinside.com 2019 - 2024. All rights reserved.