objective-cswiftplatform

Is there something like os(iOS) in Objective-C?


Swift provides a special preprocessor directive called os to check what operating system you are running:

struct A {
#if os(iOS)
    let a: AvailableOnIOS
#elseif os(tvOS)
    let a: AvailableOnTVOS
#endif
}

I am interested if there is something similar in Objective-C that can be used like

@interface A: NSObject
#if os(iOS)
@property (nonatomic, strong) AvailableOnIOS* a;
#elseif os(tvOS)
@property (nonatomic, strong) AvailableOnTVOS* a;
#endif
@end

Solution

  • The answer to your question is:

    @interface A : NSObject
    #if TARGET_OS_IOS
        @property(nonatomic) AvailableOnIOS * a;
    #elsif TARGET_OS_TV
        @property(nonatomic) AvailableOnTVOS * a;
    #endif
    @end
    

    Do not use TARGET_OS_IPHONE as that includes all embedded systems. Just as TARGET_OS_MAC includes all Apple systems.

    To quote from Apple's TargetConditionals.h header:

    +--------------------------------------------------------------------------------------+
    |                                    TARGET_OS_MAC                                     |
    | +-----+ +------------------------------------------------------------+ +-----------+ |
    | |     | |                  TARGET_OS_IPHONE                          | |           | |
    | |     | | +-----------------+ +----+ +-------+ +--------+ +--------+ | |           | |
    | |     | | |       IOS       | |    | |       | |        | |        | | |           | |
    | | OSX | | | +-------------+ | | TV | | WATCH | | BRIDGE | | VISION | | | DRIVERKIT | |
    | |     | | | | MACCATALYST | | |    | |       | |        | |        | | |           | |
    | |     | | | +-------------+ | |    | |       | |        | |        | | |           | |
    | |     | | +-----------------+ +----+ +-------+ +--------+ +--------+ | |           | |
    | +-----+ +------------------------------------------------------------+ +-----------+ |
    +--------------------------------------------------------------------------------------+
    

    The reason why MAC covers everything is because all the other operating systems are in fact stripped down macOS systems, so MAC has become a synonym for "Apple Platform". The other platforms on this level are:

    And iPhone OS (today named iOS) was the first stripped down version of macOS, all other systems are modified version of iPhone OS, that's why the layer below TARGET_OS_MAC is split into:

    And TARGET_OS_IPHONE has the following sublayers:

    There is one final sublayer below TARGET_OS_IOS and that is TARGET_OS_MACCATALYST. "Mac Catalyst" is not truly a platform of its own but instead it is a subset of the iOS API extended with desktop API functionality. This added desktop functionality is how iPadOS differs from iOS on iPhones: They are both iOS but iPadOS has additional functionality that standard iOS on iPhone has not. The entire Catalyst API was backported to macOS, so apps that are limited to the Catalyst API can run on iPads and on Macs without further modification. Note that most normal iPhone apps can also run on Macs but only on ARM Macs, whereas Catalyst apps can also run on Intel Macs, as the Catalyst APIs are also available for x86_64 systems.

    Missing in this picture is TARGET_OS_SIMULATOR which is always set when code runs in a simulator; no matter what simulator. E.g. if you want a piece of code to only be used when you run in an iOS simulator but not in other simulators (tvOS, watchOS), then you would use

    #if TARGET_OS_SIMULATOR && TARGET_OS_IOS
    
    #endif
    

    Note that this code will not run on a real iOS device either.

    Also noteworthy are the defines for different target CPUs:

    and the defines for the following properties:

    All other target conditionals are deprecated or pretty much useless in practice.