web-dev-qa-db-ja.com

Objective-cで配列を定数として宣言するにはどうすればよいですか?

次のコードは私にエラーを与えています:

//  constants.h
extern NSArray const *testArray;
//  constants.m
NSArray const *testArray = [NSArray arrayWithObjects:  @"foo", @"bar", nil];

私が得るエラーは
initializer element is not constant

または、ポインターインジケーター(*)を削除すると、次のようになります。
statically allocated instance of Objective-C class 'NSArray'

63
Andrew

要するに、できません。 NSString定数を除き、Objective-Cオブジェクトは実行時にのみ作成されるため、式を使用してオブジェクトを初期化することはできません。

いくつかのアプローチがあります。

(1)NSArray *testArrayconstキーワードなしで、アプリケーションライフサイクルの非常に早い段階で呼び出される値を設定するコードを少し用意します。

(2)配列を返す便利なクラスメソッドを宣言し、static NSArray *myArrayそのメソッド内で、それをシングルトンとして扱います(インスタンス化の方法についての無数の答えについては、 "objective-c singleton"の場合SOを検索)。

69
bbum

パーティーに少し遅れましたが、プログラムの過程で値を変更していないため、文字列のみを扱っている場合は、C配列を使用して配列を宣言することで次のことができます。

_extern NSString * const MY_CONSTANT_STRING_ARRAY[];
_

_constants.h_ファイルで、_constants.m_ファイルで、次のようにオブジェクトを追加できます。

_NSString * const MY_CONSTANT_STRING_ARRAY[] = { @"foo", @"bar" };
_

次に、メンバーにアクセスするには、Csizeof()演算子を使用してforループを実行できます。

これは明らかにCではなくNSArray配列であるため、_objectAtIndex:_のようにすべての楽しいメソッドをアタッチすることはできないため、どこかにヘルパー関数を作成できます。上記で説明した方法を使用してすべての文字列をループし、NSArray(またはNSMutableArray even)を返すプログラム。しかし、あなたが私と同じことをしていて、プログラム全体で使用するNSString値の定数配列が必要な場合、この方法が最適です。

この方法で行うと、すべての文字列配列定数を_constants.h_でカプセル化でき、この配列のシングルトンを作成する代わりに_constants.h_ファイルに_.pch_を追加することで、プログラム全体で利用できます値または小さなコードで配列を設定すると、constantsファイルから実際の定数が削除されるため、constantsファイルの目的を無効にします。

@ JesseGumpoのコメントごとに編集

sizeof()を使用して配列のサイズを決定すると問題が発生する可能性があるため、簡単な回避策は、次のように定数ファイルで配列のサイズを宣言することです。

_//.h
extern int SIZE_OF_MY_CONSTANTS_ARRAY;  

///.m
int SIZE_OF_MY_CONSTANTS_ARRAY = 2;
_

そして、forループでメンバーにアクセスするには、次のようにします。

_for (int i=0; i < SIZE_OF_MY_CONSTANTS_ARRAY; i++) 
        NSLog(@"my constant string is: %@", MY_CONSTANT_STRING_ARRAY[i]);
_

はい、これは動的に配列のサイズをキャプチャしませんが、定数ファイルで配列を宣言している場合、その配列のサイズは最初からすでにわかっているため、さらに2行のコードを追加しますが、定数ファイルに配列を持つというタスクを引き続き実行します。

誰か他に提案がある場合や、他のCトリックを知っている場合は、下にコメントを残してください!

33
AngeloS

メソッドスコープ内の静的インスタンスに対して1行で実行するマクロを次に示します。

#define STATIC_ARRAY(x, ...)   \
        static NSArray* x=nil; \
        static dispatch_once_t x##onceToken; \
        dispatch_once(&x##onceToken, ^{ x = @[ __VA_ARGS__ ]; });

使用例

    STATIC_ARRAY(foo, @"thing1", @"thing2", [NSObject new]);
9
JoeM

私にとっては、定数の配列に次の実装を使用する方が便利です

static NSString * kHeaderTitles [3] = {@ "ACCOUNT DETAILS", @ "SOCIAL NETWORK", @ "SETTINGS"};
static int kNumbers[3] = {1, 2, 3};
6
Vlad Smelov

とても簡単です。

#define arrayTitle [NSArray arrayWithObjects: @"hi",@"foo",nil]

実装前にセミコロンなしで配置します。

それが役に立てば幸い。

6
HelmiB

「Constants.h」というヘッダーファイルがあり、次の定数配列内にあります。

#define arrayOfStrings @[@"1", @"2", @"3", @"4"]
#define arraysOfIds @[@(1), @(2), @(3), @(4)]

基本的に、コードでarrayOfStringsを呼び出すと、@ [@ "1"、@ "2"、@ "3"、@ "4"]に置き換えられ、arrayOfIdsで同じことが行われます。

3