18

I have a simple app which also has a iOS 8 Today Extension (or widget). One of the things I am doing is sharing code classes between my app and my widget, because obviously this saves me from having to have multiple copies of the same code. It all works nicely apart from one problem I am having, one of the APIs UIApplication sharedApplication is coming up with an error because you can't use that on iOS 8 Widgets.

So what I was thinking of, is have a simple if statement which checks if the end target is the native app OR if it is a iOS 8 widget and then add the code in as is appropriate. Would that work?

Here is my code:

if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
    {
        CGSize ssz = sz;
        sz = CGSizeMake(ssz.height, ssz.width);
    }

How can I change this code so that is can do one of the following:

  1. Only run/compile IF the end target is a native iOS app and not a widget.
  2. OR check to see if that API is available on the target platform and then use it if it is?

I hope my question makes sense and thanks for your time, Dan.

3 Answers3

35

Run time checks are out, because Xcode won't let you compile extension code that uses sharedApplication. It has to be a compile-time check.

Unfortunately this check isn't built in, you have to add it. You need to do something like:

  1. In the project settings for the today extension, under "Other C Flags", add your own custom compiler macro. For a macro named TODAY_EXTENSION, add -DTODAY_EXTENSION:

enter image description here

  1. In your code, check this macro using something like

    #ifndef TODAY_EXTENSION
    ... app-only code here ...
    #endif
    

    Conversely, code that should only exist in the extension would look like

    #ifdef TODAY_EXTENSION
    ... extension-only code here ...
    #endif
    
Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
  • 1
    And so you can then add ```else``` statements to that ```#ifndef``` statements? –  Apr 14 '15 at 07:11
  • Also do you know why Apple have banned sharedApplication in iOS 8 Extensions? –  Apr 14 '15 at 07:13
  • You can use `#else` if you need it. You get the whole [C preprocessor](http://en.wikipedia.org/wiki/C_preprocessor), which can do a lot. As for `sharedApplication`, it's because extensions run as plugins to a separate process that can run different extensions at different times, so `sharedExtension` wouldn't work the same anyway. – Tom Harrington Apr 14 '15 at 15:34
  • Surely there is a runtime check? I need this code in an extension that is used by both the app & the extension. – mxcl Apr 19 '17 at 16:33
4

Tom's answer is right on. Another alternative is to define the macro in the prefix.pch file for your extension target, assuming you're using separate prefix files for each target.

#define TODAY_EXTENSION YES

I personally prefer this approach as you can command-click through to the macro wherever it's used to see where it's defined.

Christopher Pickslay
  • 17,523
  • 6
  • 79
  • 92
0

For a Swift project, you should add it into the build settings of the target under Swift Compiler - Custom Flags > Active Compilation Conditions.

enter image description here

Even better, I put it in my xcconfig file so it can be easily maintained:

SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) iOS_EXTENSION
TruMan1
  • 33,665
  • 59
  • 184
  • 335