Objective-Cで定数を作成する最良の方法は何ですか


156

私は学習目的でRedditクライアントを作成しています。定数が入ったファイルが必要です。Reddit-Prefix.pchすべてのファイルで定数を使用できるようにするために、ファイルにファイルをインポートすることを考えていました。それは物事を行うのに良い方法ですか?また、私は自分の調査をして定数を作成するいくつかの方法を見つけましたが、どれを使用するかわかりません。

  • #define 大きい
  • const
  • static const
  • extern const
  • enum

では、どちらの方法が望ましいのでしょうか?大会とは何ですか?「依存する」ことは知っていますが、私の質問は、具体的には次のとおりです。これらの各ソリューションのユースケースは何ですか?

また、を使用している場合extern const、ファイルをインポートする必要がありますか、それとも定数をファイルをインポートしなくてもグローバルに使用できますか?

論理的に結論できることの1つenumは、それがカスタムエラードメインのようなものを定義するときの最良の選択です(私は実際に正しいですか?)。しかし、他の人はどうですか?


stackoverflow.com/questions/11153156/…このリンクにアクセスしてください...あなたのソリューションはこの投稿にあります
ユーザー1531343

3
@BhavikKama:これは、2つの特定のソリューションを対照するより狭い質問です。
Peter Hosey 2013年

以下のために-静的定数、の#define、列挙型、このリンクは便利ですstackoverflow.com/questions/1674032/static-const-vs-define-in-cのconstのものを3代替に良い説明を提供
ユーザー1531343

enum整数値にのみ役立ちます。#define定数は任意のデータ型にすることができます。
rmaddy 2013年

conststatic const、およびextern constスコープを除き、すべて同じです。したがって、選択肢は3つしかありません。
rmaddy 2013年

回答:


385

最初の質問は、定数にどのようなスコープを持たせたいかです。これは、実際には2つの質問です。

  • これらの定数は単一のクラスに固有のものですか、それともアプリケーション全体にそれらがあるのが理にかなっていますか?
  • それらがクラス固有である場合、それらはクラスのクライアントが使用するためのものですか、それともクラス内だけですか?

それらが特定であり、単一のクラスの内部にある場合はstatic const、次のように.mファイルの先頭として宣言します。

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

それらが単一のクラスに関係するが、他のクラスによってパブリック/使用される必要がある場合は、それらをexternヘッダーのように宣言し、.mで定義します。

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

それらをグローバルにする必要がある場合は、それらをヘッダーで宣言し、対応するモジュールで、特にこれらの定数に対して定義します。

これらを混合して、どのようにグローバルにしたいかというさまざまなレベルのさまざまな定数と、単に一緒に属さないさまざまなグローバル定数とを一致させることができます。これらを別々のモジュールに配置し、それぞれに独自のヘッダーを付けることができます。欲しいです。

なんで#define

古い答えは「マクロには型情報がない」ですが、今日のコンパイラーは、変数だけでなくリテラル(マクロの展開先)のすべての型チェックを実行するのがかなり賢明です。

最近の答えは、デバッガーがマクロについて知らないためです。マクロである[myThing addObserver:self forKey:MyThingNotificationKey]場合、デバッガーコマンドで言うことはできませんMyThingNotificationKey。デバッガはそれが変数である場合にのみそれを知ることができます。

なんでenum

まあ、rmaddyはコメントで私を打ち負かしました:enum整数定数しか定義できません。シリアルID番号、ビットマスク、4バイトコードなど。

それらの目的のために、enum素晴らしいです、そしてあなたは絶対にそれを使うべきです。(さらに良いのはNS_ENUMand NS_OPTIONSマクロを使用することです。)他のものについては、他のものを使用する必要あります。enum整数以外は何もしません。

そして他の質問

Reddit-Prefix.pchファイルにファイルをインポートして、すべてのファイルで定数を使用できるようにすることを考えていました。それは物事を行うのに良い方法ですか?

おそらく無害ですが、おそらく過剰です。定数ヘッダーを必要な場所にインポートします。

これらの各ソリューションのユースケースは何ですか?

  • #define:かなり限定されています。正直なところ、これを定数に使用する十分な理由があるかどうかはわかりません。
  • const:ローカル定数に最適です。また、これをヘッダーで宣言し、現在定義しているものに使用する必要があります。
  • static const:ファイル固有(またはクラス固有)の定数に最適です。
  • extern const:ヘッダーで定数をエクスポートする場合は、これを使用する必要があります。

また、を使用している場合extern const、ファイルをインポートする必要がありますか、それとも定数をファイルをインポートしなくてもグローバルに使用できますか?

ファイルは、使用する各ファイルまたはプレフィックスヘッダーにインポートする必要があります。


3
ファイルで一緒に使用static NSString *constしないのはなぜ.hですか?
Iulian Onofrei 2015年

3
@IulianOnofrei:フレームワークではなく、アプリケーション内にある場合は可能です。使用する場合static NSString *const foo = @"foo";、ヘッダーによって文字列が決定され、文字列はどこでも同じである必要があります。文字列を変更し、異なる当事者が異なるバージョンのヘッダーを異なる文字列で使用すると、実行時に文字列が一致しなくなります。時間。フレームワークでは、シンボルへのアクセスのみを提供し、フレームワークがそのシンボルの真の値の唯一のソースになるようにして、全員が1つの場所から同じ文字列を取得するようにします。それexternはあなたを得るものです。
Peter Hosey、2015年

#defines に関する追加の注意:それらはメモリ内で同じアドレスを持っていることが保証されていません(宣言方法によっては、使用されるたびに新しいインスタンスを割り当てる場合があります)myObject == MyDefine。しかしそうmyObject == MyStaticConstするでしょう。
Ben Leggiero 2016年

それは次のように綴りで意味をなすんstatic NSString *const代わりにstatic NSString const*?違いはありますか?
kokos8998 2016年

@ kokos8998違いはありますか?はい、そうです。static NSString const *と同じでstatic const NSString *、「定数NSStringへの(変更可能な)ポインタ」を意味します。NSStringはすでに不変であるため、ここでは少し役に立ちません。何をしたいかstatic NSString * const-これは「NSStringへの定数ポインタ」
David

8

FOUNDATION_EXPORT

FOUNDATION_EXPORTより少し互換性のために使用することを検討してくださいexternファウンデーションで定義されており、C、C ++、およびWin32の互換性のあるフォーマットにコンパイルされる。

NSObjCRuntime.hで定義されているとおり

#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.