OS X目标的预处理器宏?

时间:2012-08-26 18:50:52

标签: objective-c ios xcode macos cocoa

我有一个同时拥有iOS和OS X目标的项目。在编译OS X时是否有预处理器宏?我试过这个:

#if TARGET_OS_MAC
@interface BFNode : NSObject <NSPasteboardReading, NSPasteboardWriting> {
#else
@interface BFNode : NSObject {
#endif

但是TARGET_OS_MAC似乎不起作用。当我尝试在iOS上运行应用程序时,我遇到编译器错误,因为它尝试编译第一行并且在iOS上没有定义NSPasteboardReading协议。

我知道也有TARGET_OS_IPHONE。如果我使用它并交换它有效的@interface声明。

但是我有很多地方有代码,没有iOS版本,所以我也需要OS X的宏。

SOLUTION:

我最终在.pch文件中定义了一个新宏:

#define TARGET_OSX TARGET_OS_IPHONE == 0

7 个答案:

答案 0 :(得分:10)

如果您正在使用Swift,那么language feature就是一个很棒的What it means to escape a string。如果您正在使用Objective-C,那么执行以下操作通常很有用:

#include <TargetConditionals.h>

#if TARGET_OS_IPHONE
    @import UIKit;
#else
    @import AppKit;
#endif

了解TARGET_OS_*定义会使这更有意义。最值得注意的是,TARGET_OS_MAC是任何Apple平台,这是非常出乎意料的。 !TARGET_OS_IPHONE是macOS,TARGET_OS_IPHONE是除此之外的任何内容。 iOS,tvOS和watchOS有更具体的定义。

来自TargetConditions.h

TARGET_OS_* 
These conditionals specify in which Operating System the generated code will
run.  Indention is used to show which conditionals are evolutionary subclasses.  

The MAC/WIN32/UNIX conditionals are mutually exclusive.
The IOS/TV/WATCH conditionals are mutually exclusive.


    TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
    TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
    TARGET_OS_MAC             - Generated code will run under Mac OS X variant
       TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator 
          TARGET_OS_IOS             - Generated code will run under iOS 
          TARGET_OS_TV              - Generated code will run under Apple TV OS
          TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
       TARGET_OS_SIMULATOR      - Generated code will run under a simulator
       TARGET_OS_EMBEDDED       - Generated code for firmware

    TARGET_IPHONE_SIMULATOR   - DEPRECATED: Same as TARGET_OS_SIMULATOR
    TARGET_OS_NANO            - DEPRECATED: Same as TARGET_OS_WATCH

答案 1 :(得分:5)

这是因为在为iOS构建时也定义了TARGET_OS_MAC

请参阅http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

我会尝试通过目标上的构建设置构建我自己的目标特定定义。

答案 2 :(得分:5)

根据TargetConditionals.h中的文档(似乎截至2016年;任何平台):

+------------------------------------------------+
|                TARGET_OS_MAC                   |
| +---+  +-------------------------------------+ |
| |   |  |          TARGET_OS_IPHONE           | |
| |OSX|  | +-----+ +----+ +-------+ +--------+ | |
| |   |  | | IOS | | TV | | WATCH | | BRIDGE | | |
| |   |  | +-----+ +----+ +-------+ +--------+ | |
| +---+  +-------------------------------------+ |
+------------------------------------------------+

这告诉我们:

  • TARGET_OS_MAC1用于(可能)在Apple平台上运行的任何Cocoa应用程序。

    • TARGET_OS_OSX对于macOS目标只有1
    • 对于任何非Mac Apple产品,
    • TARGET_OS_IPHONE1
      • TARGET_OS_IOS仅适用于iOS
      • TARGET_OS_TV仅适用于tvOS
      • TARGET_OS_WATCH仅适用于watchOS
      • TARGET_OS_BRIDGE仅适用于bridgeOS(目前它甚至不支持第三方应用,因此您可能始终认为这是0

此外,还定义了这些:

  • TARGET_OS_SIMULATOR仅适用于iOS, tvOS, and watchOS simulators。您可以使用上述#define s
  • 进一步优化此功能
  • TARGET_OS_WIN32以防万一你想使用Apple的SDK制作Windows应用程序。我不会亲自了解除Apple以外的任何人(如iTunes,Safari和QuickTime)
  • TARGET_OS_UNIX适用于非macOS UNIX系统

这些已被弃用,不应再使用了。也就是说,您可能会在代码中找到它们,所以这就是它们的含义:

  • TARGET_IPHONE_SIMULATOR用于表示iPhoneOS模拟器
  • TARGET_OS_EMBEDDED用于表示iOS,tvOS和watchOS非模拟设备
  • TARGET_OS_NANO可能用来表示iPod Nano(我无法在线找到任何历史用法)

需要注意的是the TargetConditionals.h used in swift-corelibs-foundation明显不同,包括适用于Android,Cygwin的#define以及其他未明确支持的技术工作平台。

我不完全确定如何做到这一点。我猜它是为了编译Swift Foundation框架,而不是为了消费它,因为Swift并没有消耗#define

答案 3 :(得分:1)

在TargetConditionals.h中查找整个列表,包括:

#define TARGET_OS_MAC               1
#define TARGET_OS_IPHONE            1 
#define TARGET_IPHONE_SIMULATOR     1 

答案 4 :(得分:1)

从Xcode 8 GM开始,这是iOS 10.0中 TargetConditionals.h 的相关部分:

#define TARGET_OS_MAC               1
#define TARGET_OS_WIN32             0
#define TARGET_OS_UNIX              0
#define TARGET_OS_OSX               0
#define TARGET_OS_IPHONE            1
#define TARGET_OS_IOS               1
#define TARGET_OS_WATCH             0
#define TARGET_OS_BRIDGE            0
#define TARGET_OS_TV                0
#define TARGET_OS_SIMULATOR         0
#define TARGET_OS_EMBEDDED          1 
#define TARGET_IPHONE_SIMULATOR     TARGET_OS_SIMULATOR /* deprecated */
#define TARGET_OS_NANO              TARGET_OS_WATCH /* deprecated */

(在Xcode文本编辑器上方的'breadcrumb'中,iOS 10.0 > usr/include > TargetConditionals.h

...对于macOS来说,这是同一个文件:

#define TARGET_OS_MAC               1
#define TARGET_OS_WIN32             0
#define TARGET_OS_UNIX              0
#define TARGET_OS_OSX               1
#define TARGET_OS_IPHONE            0
#define TARGET_OS_IOS               0
#define TARGET_OS_WATCH             0
#define TARGET_OS_BRIDGE            0
#define TARGET_OS_TV                0
#define TARGET_OS_SIMULATOR         0
#define TARGET_OS_EMBEDDED          0 
#define TARGET_IPHONE_SIMULATOR     TARGET_OS_SIMULATOR /* deprecated */
#define TARGET_OS_NANO              TARGET_OS_WATCH /* deprecated */ 

(在Xcode文本编辑器上方的'breadcrumb'中,macOS 10.12 > usr/include > TargetConditionals.h

TARGET_OS_MAC在两个平台上定义为 1 ,但TARGET_OS_OSX仅在 1

在文件的评论中,它们描述如下:

  
      
  • TARGET_OS_MAC:生成的代码将在Mac OS X变体下运行。
  •   
  • TARGET_OS_OSX:生成的代码将在OS X设备下运行。
  •   

我想当时的某些时候(可能是在宣布推出iPhone的时候?)有人认为iOS(né“iPhone OS”)符合“Mac OS X变种”的定义。

答案 5 :(得分:0)

我建议使用它:

#define TARGET_OS_OSX (!(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH))

答案 6 :(得分:0)

我遇到了同样的情况,但是Swift需要它。

Apple开发者论坛上的此答案对于处理您所处的NSPasteboard协议非常有帮助,但对于Swift。

https://forums.developer.apple.com/thread/16757

我最终做了:

#if os(iOS) || os(watchOS)
  public protocol TFPasteboardReading { }
  public protocol TFPasteboardWriting { }
#elseif os(macOS)
  public typealias TFPasteboardReading=NSPasteboardReading
  public typealias TFPasteboardWriting=NSPasteboardWriting
#endif


@objc(TFCategory)
public class TFCategory: TFBaseModel, TFPasteboardReading, TFPasteboardWriting {

...

}

那样,为macOS定义了TFPasteboardReadingTFPasteboardWriting,分别表示NSPasteboardReadingNSPasteboardWriting,而在iOS中则没有意义,但仍可以在iOS中引用。因此,这两种代码都可以正确编译。