有谁知道如何从代码中检测您是否在应用程序扩展中运行?
我有一个在应用程序和扩展程序之间共享类的应用程序。应用程序代码使用
[UIApplication sharedApplication]
但这在扩展中不可用,因此它不会编译:
“sharedApplication”不可用:不可用 iOS(应用程序扩展)
所以我需要一种方法来检测我是否在扩展中,并使用
sharedApplication
的替代方案(如果是这种情况)。
您可以使用预处理器宏:
在项目设置中,使用顶部栏中的下拉菜单选择您的扩展目标:
然后:
- 点击
Build Settings
- 在
Preprocessor Macros
下查找(或搜索)Apple LLVM 6.0 - Preprocessing
- 在调试和发布部分添加
或您选择的任何其他名称。TARGET_IS_EXTENSION
然后在你的代码中:
#ifndef TARGET_IS_EXTENSION // if it's not defined
// Do your calls to UIApplication
#endif
正如 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
}
预处理器宏大部分情况下都可以工作,但在共享库(例如cocoapods或共享框架)中不起作用。
您也可以使用以下代码。
@implementation ExtensionHelpers
+(BOOL) isAppExtension
{
return [[[NSBundle mainBundle] executablePath] containsString:@".appex/"];
}
@end
此工作通过检查捆绑包可执行路径来完成,因为只有应用程序扩展具有扩展名“.appex”。
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`
您可以在扩展目标上添加预处理器宏,然后使用类内部的
#ifdef
进行检查。
对于我的共享库,我创建了一个单独的目标,其应用程序扩展标志设置为 yes,并在该特定目标的构建设置中使用了预处理器宏。
在开发框架(例如 Swift Package)时,使用预处理器宏提供的答案仍然不能很好地工作。
相反,您可以将属性
@available(iOSApplicationExtension, unavailable)
用于需要调用UIApplication.shared
的方法,然后安全地调用shared
。