xcode OS X 目标的预处理器宏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12132933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 01:20:29  来源:igfitidea点击:

Preprocessor macro for OS X targets?

objective-ciosxcodemacoscocoa

提问by DrummerB

I have a project that has both an iOS and an OS X target. Is there a preprocessor macro that is true when I'm compiling for OS X? I tried this:

我有一个同时具有 iOS 和 OS X 目标的项目。当我为 OS X 编译时,是否有一个正确的预处理器宏?我试过这个:

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

But TARGET_OS_MACdoesn't seem to work. When I try to run the app on iOS I get a compiler error, because it tries to compile the first line and there is no NSPasteboardReadingprotocol defined on iOS.

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

I know there is TARGET_OS_IPHONEtoo. If I use that and swap the @interfacedeclarations it works.

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

But there are a lot of places where I have code, that has no iOS version, so I need a macro for OS X too.

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

SOLUTION:

解决方案:

I ended up defining a new macro in the .pch file:

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

#define TARGET_OSX TARGET_OS_IPHONE == 0

采纳答案by Till

That is because TARGET_OS_MACis defined when building for iOS as well.

那是因为TARGET_OS_MAC在为 iOS 构建时也定义了它。

See http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.htmlon that.

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

I would try and build my own target specific define via build-settings on the target.

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

回答by Ben Leggiero

As per the documentation in TargetConditionals.h(it seems, as of 2019; any platform):

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

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

This tells us:

这告诉我们:

  • TARGET_OS_MACwill be 1for (probably) any Cocoa application running on an Apple platform.

    • TARGET_OS_OSXwill only be 1for macOS targets
    • TARGET_OS_IPHONEwill be 1for any non-Mac Apple products
      • TARGET_OS_IOSis just for iOS
      • TARGET_OS_TVis just for tvOS
      • TARGET_OS_WATCHis just for watchOS
      • TARGET_OS_BRIDGEis just for bridgeOS(which currently doesn't even support 3rd-party apps so you'll likely always see that be 0)
      • TARGET_OS_MACCATALYSTis just for Project Catalyst. It seems TARGET_OS_UIKITFORMACwill also work.
  • TARGET_OS_MAC1用于(可能)在 Apple 平台上运行的任何 Cocoa 应用程序。

    • TARGET_OS_OSX将仅1适用于 macOS 目标
    • TARGET_OS_IPHONE1适用于任何非 Mac Apple 产品
      • TARGET_OS_IOS仅适用于 iOS
      • TARGET_OS_TV仅适用于 tvOS
      • TARGET_OS_WATCH仅适用于 watchOS
      • TARGET_OS_BRIDGE仅适用于bridgeOS(目前它甚至不支持 3rd-party 应用程序,因此您可能总是会看到它0
      • TARGET_OS_MACCATALYST仅适用于Project Catalyst。它似乎TARGET_OS_UIKITFORMAC也将工作。


Additionally, these are defined:

此外,还定义了这些:

  • TARGET_OS_SIMULATORis just for iOS, tvOS, and watchOS simulators. You can further refine this using the above #defines
  • TARGET_OS_WIN32is in case you wanna use Apple's SDKs to make Windows apps. I don't personally know of any other than Apple's own (like iTunes, Safari, and QuickTime)
  • TARGET_OS_UNIXis for non-macOS UNIX systems
  • TARGET_OS_SIMULATOR仅适用于iOS、tvOS 和 watchOS 模拟器。您可以使用上述#defines进一步细化
  • TARGET_OS_WIN32以防万一您想使用 Apple 的 SDK 来制作 Windows 应用程序。除了 Apple 自己的(例如 iTunes、Safari 和 QuickTime),我个人不知道其他任何软件
  • TARGET_OS_UNIX适用于非 macOS UNIX 系统

And these are deprecated, and should not be used anymore. That said, you might find them in code you have to maintain, so here's what they meant:

这些已被弃用,不应再使用。也就是说,您可能会在必须维护的代码中找到它们,因此它们的含义如下:

  • TARGET_IPHONE_SIMULATORused to mean the iPhoneOSsimulator
  • TARGET_OS_EMBEDDEDused to mean iOS, tvOS, and watchOS non-simulated devices
  • TARGET_OS_NANOprobably used to mean iPod Nano (I can't find any historical usage online)
  • TARGET_IPHONE_SIMULATOR曾经是指iPhoneOS模拟器
  • TARGET_OS_EMBEDDED过去指的是 iOS、tvOS 和 watchOS 非模拟设备
  • TARGET_OS_NANO可能曾经是指 iPod Nano(我在网上找不到任何历史用法)


Something else to note is that the TargetConditionals.hused in swift-corelibs-foundationis significantly different, and includes #defines for Android, Cygwin, and other not-explicitly-supported-but-they-technically-work platforms.

别的东西要注意的是,TargetConditionals.h所使用的SWIFT corelibs基金会是显著不同,包括#defineS代表的Android,Cygwin的,和其他未明确支持的,但是,他们-技术上的工作平台。

I'm not entirely sure what to make of this. I would guess it's for compiling the Swift Foundation framework, and not for consuming it, since Swift doesn't consume #defines.

我不完全确定该怎么做。我猜它是为了编译 Swift Foundation 框架,而不是为了使用它,因为 Swift 不使用#defines。

回答by Sam Soffes

If you're using Swift, there's a great language featurefor this. If you're using Objective-C, it's often useful to do something like this:

如果您使用的是 Swift,那么这里有一个很棒的语言功能。如果您使用的是 Objective-C,那么执行以下操作通常很有用:

#include <TargetConditionals.h>

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

Understanding the TARGET_OS_*defines will make this make a lot more sense. Most notably, TARGET_OS_MACis any Apple platform which is pretty unexpected. !TARGET_OS_IPHONEis macOS and TARGET_OS_IPHONEis anything besides that. There are more specific defines for iOS, tvOS, and watchOS.

了解TARGET_OS_*定义将使这更有意义。最值得注意的是,TARGET_OS_MAC任何苹果平台都非常出人意料。!TARGET_OS_IPHONE是 macOS 以及TARGET_OS_IPHONE除此之外的任何东西。iOS、tvOS 和 watchOS 有更具体的定义。

From TargetConditions.h:

来自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

回答by Caleb

Look in TargetConditionals.h for an entire list, including:

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

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

回答by Nicolas Miari

As of Xcode 8 GM, this is the relevant section of TargetConditionals.hin iOS 10.0:

从 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 */

(In the 'breadcrumb' above the text editor in Xcode, iOS 10.0 > usr/include > TargetConditionals.h)

(在 Xcode 中文本编辑器上方的“面包屑”中,iOS 10.0 > usr/include > TargetConditionals.h

...And this is the same file, for macOS:

...这是相同的文件,对于 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 */ 

(In the 'breadcrumb' above the text editor in Xcode, macOS 10.12 > usr/include > TargetConditionals.h)

(在 Xcode 中文本编辑器上方的“面包屑”中,macOS 10.12 > usr/include > TargetConditionals.h

TARGET_OS_MACis defined as 1on both platforms, but TARGET_OS_OSXis 1only on macOS.

TARGET_OS_MAC被定义为1两个平台上,但TARGET_OS_OSX1只在MacOS。

In the file's comments, they are described as follows:

在文件的注释中,它们的描述如下:

  • TARGET_OS_MAC: Generated code will run under Mac OS X variant.
  • TARGET_OS_OSX: Generated code will run under OS X devices.
  • TARGET_OS_MAC:生成的代码将在 Mac OS X 变体下运行。
  • TARGET_OS_OSX:生成的代码将在 OS X 设备下运行。

I guess at some point back then (perhaps around when the iPhone was announced?) somebody decided that iOS (né "iPhone OS") fits the definitions of "Mac OS X variant".

我想在当时的某个时候(也许是在 iPhone 发布的时候?)有人认为 iOS(né“iPhone OS”)符合“Mac OS X 变体”的定义。

回答by Tap Forms

I ran into this same situation, but needed it for Swift.

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

This answer here on the Apple developer forums was very helpful in dealing with the NSPasteboardprotocols in your situation, but for Swift.

Apple 开发者论坛上的这个答案对于处理NSPasteboard您的情况下的协议非常有帮助,但对于 Swift 而言。

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

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

I ended up doing:

我最终做了:

#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 {

...

}

That way TFPasteboardReadingand TFPasteboardWritingis defined for macOS meaning NSPasteboardReadingand NSPasteboardWritingrespectively and in iOS it has no meaning, but can still be referenced in iOS. So the code compiles properly for both.

那种方式TFPasteboardReading并分别TFPasteboardWriting为 macOSNSPasteboardReadingNSPasteboardWritingiOS定义,它没有意义,但仍然可以在 iOS 中引用。因此,代码可以为两者正确编译。

回答by erkanyildiz

I would recommend using this:

我会建议使用这个:

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