44

コードを共有する Mac アプリケーションと iPad アプリケーションを含むプロジェクトに取り組んでいます。条件付きコンパイル スイッチを使用して Mac 固有のコードを iPhone プロジェクトから除外したり、その逆を行うにはどうすればよいですか? TARGET_OS_IPHONETARGET_OS_MACはどちらも 1 であることに気付きました。したがって、どちらも常に true です。特定のターゲット用にコンパイルするときにのみ true を返す、使用できる別のスイッチはありますか?

ほとんどの場合、ファイルを2 つのプロジェクトのプリコンパイル ヘッダーに移動#include <UIKit/UIKit.h>して連携させることができました。#include <Cocoa/Cocoa.h>RSS フィードと Evernote からデータを取得するモデルといくつかのユーティリティ コードを共有しています。

特に、[NSData dataWithContentsOfURL:options:error:]iOS 3.2 以前および Mac OS 10.5 以前では、iOS 4 および Mac OS 10.6 の場合とは異なり、この関数は options パラメーターに対して異なる定数を使用します。私が使用している条件は次のとおりです。

#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2)) || (TARGET_OS_MAC && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5))

これは機能しているようですが、これが防弾であることを確認したいと思います。私の理解では、Mac のバージョンが 10.6 に設定されていて、iOS のバージョンが 3.2 に設定されている場合、iOS 3.2 用にコンパイルしていても新しい定数が使用されますが、これは正しくないようです。

助けてくれてありがとう!

4

4 に答える 4

71

あなたは観察を間違えました。:)

TARGET_OS_MACMac または iPhone アプリケーションをビルドする場合は 1 になります。そうですよね、こういうのじゃダメなんです。

ただし、TARGET_OS_IPHONEMac アプリケーションをビルドする場合は 0 です。TARGET_OS_IPHONEこの目的のために、ヘッダーで常に使用しています。

このような:

#if TARGET_OS_IPHONE
// iOS code
#else
// OSX code
#endif

これに関する優れたチャートは次のとおりです。 http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

于 2010-07-06T00:39:54.163 に答える
8

「正しいことは、新しい定数を使用することです。ヘッダーを見ると、列挙型の古い定数と同等に宣言されていることがわかります。つまり、新しい定数は古いリリース(両方の定数)でも機能します。同じものにコンパイルし、列挙型はアプリにコンパイルされるため、バイナリの互換性を損なうことなく変更することはできません)それを行わない唯一の理由は、古いSDKを再度ビルドし続ける必要がある場合です(これはとは異なります)古いリリースをサポートします。これは、新しいSDKに対してコンパイルするときに実行できます)。

OSのバージョンに基づいて実際に異なるフラグを使用したい場合(定数の名前を変更するだけでなく、新しいバージョンが実際に新しい機能を追加したため)、実行できる2つの賢明なことがありますが、どちらも上記のマクロでは実現できません。

  1. 許可されている最小バージョンが導入されたバージョンよりも大きい場合を除いて、常に古いフラグを使用するには(次のようなもの):

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options = NSMappedRead;
    #end
    
  2. 条件付きで、新しいバージョンでのみ使用できるビルドで新しい値のみを使用し、コードでコンパイルして、両方のバージョンをサポートするビルドの実行時にフラグを決定します。

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options;
      if ([[UIDevice currentDevice] systemVersion] compare:@"4.0"] != NSOrderedAscending) {
         options = NSDataReadingMapped;
      } else {
        options = NSMappedRead;
      }
    #end
    

実際にこの比較を頻繁に行っている場合は、結果を[[UIDevice currentDevice] systemVersion] compare:@"4.0"]どこかに隠しておく必要があることに注意してください。また、通常、バージョン比較を行う代わりに、弱いリンクなどを使用して機能を明示的にテストする必要がありますが、これは列挙型のオプションではありません。

于 2010-07-05T18:42:34.440 に答える
8

使用するマクロは、SDK ヘッダー ファイルで定義されていますTargetConditionals.h。10.11 SDK から取得:

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

ここではすべてが「Mac OS X バリアント」でTARGET_OS_MACあるため、この場合は役に立ちません。macOS 専用にコンパイルするには、たとえば次のようにします。

#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
    // macOS-only code
#endif

更新: 新しいヘッダー (Xcode 8+?) はTARGET_OS_OSX、macOS 用に特別に定義されています。(h / t @OldHorse)、これはうまくいくはずです:

#if TARGET_OS_OSX
 // macOS-only code
#endif
于 2016-07-05T16:00:12.197 に答える