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

Ios 如何检测代码是否在主应用程序或应用程序扩展目标中运行?,ios,uiapplicationdelegate,ios-app-extension,Ios,Uiapplicationdelegate,Ios App Extension,如果你在应用程序扩展中运行,有人知道你是如何从代码中检测的吗 我有一个在应用程序和扩展程序之间共享类的应用程序。应用程序代码使用[UIApplication sharedApplication],但这在扩展中不可用,因此它不会编译为: “sharedApplication”不可用:iOS(应用程序扩展)不可用 因此,我需要一种方法来检测我是否在扩展中,并在这种情况下使用一种替代方法来替代sharedApplication。您可以在扩展目标上添加一个预处理器宏,然后在类中使用\ifdef进行检查。

如果你在应用程序扩展中运行,有人知道你是如何从代码中检测的吗

我有一个在应用程序和扩展程序之间共享类的应用程序。应用程序代码使用
[UIApplication sharedApplication]
,但这在扩展中不可用,因此它不会编译为:

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


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

您可以在扩展目标上添加一个预处理器宏,然后在类中使用
\ifdef
进行检查。

您可以使用预处理器宏:

在“项目设置”中,使用顶部栏中的下拉列表选择扩展目标:

然后:

  • 单击生成设置
  • 在苹果LLVM 6.0-预处理下查找(或搜索)
    预处理器宏
  • 在调试和发布部分添加
    TARGET\u是\u扩展名
    或您选择的任何其他名称
  • 然后在代码中:

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

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

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

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

    这是通过检查bundle executablePath来实现的,因为只有应用程序扩展具有扩展名“.appex”。

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

    如所述:

    在基于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
    }
    
    斯威夫特5
    圣诞老人提出的解决办法对我不起作用

    起作用的是:

  • 选择扩展目标
  • 生成设置
  • 搜索“自定义标志”
  • 添加一个新的标志(例如:“扩展”)以进行调试和发布
  • 现在代码是:

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

    谢谢,这种方法是有效的,但事实上,我需要用另一种方法来检测。如果不是扩展,请使用UIApplication。无论如何,我在应用程序目标生成设置中用一个标志解决了这个问题,将它标识为应用程序,而不是扩展。@MarkBridges对此表示抱歉。我在给未来读者的回答中修正了这个问题。这个解决方案不适用于框架中的代码。我们目前正在检查应用程序包的名称,以查看代码是否在扩展中运行,但我希望找到更好的方法。请描述您的代码。我也面临同样的问题,我需要添加什么标志或代码,然后应用程序将根据应用程序或扩展选择。记住,我创建了共享框架,这些代码应该基于bundle id执行。我的代码流似乎根本没有进入ifdef。知道为什么吗?我在编译共享库时仍然会遇到编译错误,因为它的“仅需要应用程序扩展安全API”标志设置为“是”。在仍然使用上面编写的代码时,如何避免编译错误?我不建议在生产环境中使用-[NSString containsString:],原因有二:1。它没有发布API,即官方帮助页面没有提到它(这可能是一个bug,但无论如何);2.它将在iOS7上崩溃。改为使用-[NSString rangeOfString:]。@AlexanderVasenin 2:它记录在NSString.h中,并清楚地标记为在iOS 8+上可用。请检查此线程。还有一个没有预处理器宏的解决方案宏这应该是选定的答案,这比依赖预处理器宏要好得多。同意,这更干净。不是真正干净,它是间接的,如果扩展发生变化,它可能在将来发生变化,加上条件编译将允许您排除无法在扩展中编译的资源或方法。这太完美了!谢谢:)
    #if EXTENSION
    // IF is extension (SIRI) we do stuff
    #else
    // ELSE is main app do more stuff
    #endif