私は、コードを共有するMacアプリケーションとiPadアプリケーションを含むプロジェクトに取り組んでいます。条件付きコンパイルスイッチを使用して、Mac固有のコードをiPhoneプロジェクトから除外したり、その逆を行うにはどうすればよいですか? _TARGET_OS_IPHONE
_と_TARGET_OS_MAC
_はどちらも1であるため、どちらも常にtrueであることに気付きました。特定のターゲット用にコンパイルするときにのみtrueを返す、使用できる別のスイッチはありますか?
ほとんどの場合、_#include <UIKit/UIKit.h>
_と_#include <Cocoa/Cocoa.h>
_を2つのプロジェクトのプリコンパイルヘッダーに移動することで、ファイルを連携させることができます。 RSSフィードとEvernoteからデータをフェッチするモデルといくつかのユーティリティコードを共有しています。
特に、_[NSData dataWithContentsOfURL:options:error:]
_関数は、iOS 4およびMac OS 10.6の場合とは異なり、オプションパラメーターiOS 3.2以前およびMac OS 10.5以前の場合とは異なる定数を取ります。私が使用している条件は次のとおりです:
#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用にコンパイルされていても、新しい定数が使用されます。これは正しくないようです。
助けてくれてありがとう!
観察を間違えました。 :)
TARGET_OS_MAC
は、MacまたはiPhoneアプリケーションをビルドするときに1になります。そうです、このようなことにはまったく役に立たないのです。
しかしながら、 TARGET_OS_IPHONE
は、Macアプリケーションのビルド時には0です。私が使う TARGET_OS_IPHONE
この目的のために、常に私のヘッダーで。
このような:
#if TARGET_OS_IPHONE
// iOS code
#else
// OSX code
#endif
これに関するすばらしいチャートはここにあります: http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html
使用するマクロは、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+?)に、macOS専用に定義されたTARGET_OS_OSX
が追加されました。 (h/t @OldHorse)、これはうまくいくはずです:
#if TARGET_OS_OSX
// macOS-only code
#endif
「正しいことは、新しい定数を使用することだけです。ヘッダーを見ると、列挙型の古い定数と同等に宣言されていることがわかります。つまり、新しい定数は古いリリースでも動作します(両方の定数)同じものにコンパイルします。列挙型はアプリにコンパイルされるため、バイナリ互換性を損なうことなく変更することはできません。これを行わない唯一の理由は、古いSDKを再度ビルドし続ける必要がある場合です(これは、古いリリースをサポートします。これは、新しいSDKに対してコンパイルするときに実行できます)。
OSバージョンに基づいて異なるフラグを実際に使用したい場合(新しいバージョンでは、定数の名前を変更するだけでなく、実際に新しい機能が追加されたため)、2つの賢明な方法があり、どちらも上記のマクロでは実行できません。
許可された最小バージョンがそれらが導入されたバージョンより大きい場合を除いて、常に古いフラグを使用するには(次のようなもの):
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
NSDataReadingOptions options = NSDataReadingMapped;
#else
NSDataReadingOptions options = NSMappedRead;
#end
新しいバージョンでのみ実行できるビルドで新しい値のみを条件付きで使用し、コードでコンパイルして、両方のバージョンをサポートするビルドの実行時にフラグを決定します。
#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"]
の結果をどこかに隠しておく必要があることに注意してください。また、バージョン比較を行う代わりに、弱リンクなどを使用して機能を明示的にテストしたい場合もありますが、これは列挙型のオプションではありません。
使用する一連のマクロにTARGET_OS_OSXが含まれるようになりました。
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_OSX - Generated code will run under OS X devices
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_BRIDGE - Generated code will run under Bridge devices
TARGET_OS_SIMULATOR - Generated code will run under a simulator
TARGET_OS_EMBEDDED - Generated code for firmware
MacOSコードの条件付きコンパイルでは問題なく動作するようです。