3

最新の SDK を使用して iOS アプリケーションを開発しています。

私はこの列挙型を持っています:

typedef enum BoxTypeValues {
    Speed,
    FPS,
    Altitude,
    Location,
    Accuracy
} BoxType;

そして、そのすべての値をスローして、それらを に変換することを繰り返したいと思いますNSString

私はこのようにしていますが、非常にハードコードされています:

+ (NSArray*)BoxTypeValues
{
    return [NSArray arrayWithObjects:@"Speed", @"FPS", @"Altitude", @"Location",
            @"Accuracy", nil];
}

+ (NSString*)BoxTypeToString:(BoxType)aType
{
    NSString* result = nil;

    switch (aType)
    {
        case Speed:
            result = @"Speed";
            break;
        case FPS:
            result = @"FPS";
            break;
        case Altitude:
            result = @"Altitude";
            break;
        case Location:
            result = @"Location";
            break;
        case Accuracy:
            result = @"Accuracy";
            break;

        default:
            break;
    }
    return result;
}

何かアドバイス?

4

4 に答える 4

6

列挙値を文字列に変換することは、マクロが大いに役立つまれなケースの 1 つです。例えば:

- (NSString*)BoxTypeToString:(BoxType)aType
{
#define CASE(VALUE) case (VALUE): return @( #VALUE )
    switch (aType) {
            CASE(Speed);
            CASE(FPS);
            CASE(Altitude);
            CASE(Location);
            CASE(Accuracy);

        default:
            // should not get here
            assert(0);
            break;
    }
#undef CASE
    return nil;
}

メソッドBoxTypeValuesは次のようになります。

- (NSArray*)BoxTypeStringValues
{
    return @[
        [self BoxTypeToString:Speed],
        [self BoxTypeToString:FPS],
        [self BoxTypeToString:Altitude],
        [self BoxTypeToString:Location],
        [self BoxTypeToString:Accuracy]
      ];
}

これは、リファクタリング操作で列挙値の名前を変更した後でも引き続きうまく機能します。CASE他のコードとの競合を避けるために、マクロに何らかの固有のプレフィックスを付けたい場合があります。

列挙値の列挙に関しては、値がシーケンシャルであり、標準の for ループを使用することに依存できない限り、運が悪いです(他の人が示唆しているように)。

于 2013-04-04T10:03:36.473 に答える
2
  + (NSString*)BoxTypeToString:(BoxType)aType{
    return [BoxTypeValues objectAtIndex:aType];
}

メソッドを変更するだけで、switch-case を使用する必要はありません。

于 2013-04-04T10:07:20.693 に答える
1

この問題に何度も遭遇しました。Java enum を見た人なら誰でも、Obj-C にもこの機能を持たせたいと思っています。

解決策の 1 つは、列挙型の代わりにクラスを使用することです。を使いたい場合enumsは、 と呼ばれる優れたプリプロセッサ手法がありX-Macrosます。

最初に値を定義しましょう。

#define BOX_TYPE_DEFINITIONS \
    BOX_TYPE_DEFINITION(Invalid, = 0) \
    BOX_TYPE_DEFINITION(Speed,) \
    BOX_TYPE_DEFINITION(FPS,) \
    BOX_TYPE_DEFINITION(Altitude,) \
    BOX_TYPE_DEFINITION(Location,) \
    BOX_TYPE_DEFINITION(Accuracy,)

今列挙型

#define BOX_TYPE_DEFINITION(name, intValue) name intValue,

typedef enum {
    BOX_TYPE_DEFINITIONS
} BoxType;

#undef BOX_TYPE_DEFINITION

そして「to string」機能

#define BOX_TYPE_DEFINITION(name, intValue) [name] = @#name, 

NSString* BoxTypeStringTable[] = {
    BOX_TYPE_DEFINITIONS
};

#undef BOX_TYPE_DEFINITION

#define NUM_BOX_TYPES sizeof(BoxTypeStringTable) / sizeof(NSString*)

NSString* NSStringFromBoxType(BoxType type) {
    return BoxTypeStringTable[type];
}

このテクニックが非常に強力な理由は 3 つあります

  1. 値を追加/削除する場合は、1 か所でのみ行います
  2. マクロとして値のリストがあり、すべての値を含むほぼすべてのコードを生成できます。
  3. 列挙値に他の属性を追加できます (本当にクラスを使用したくないですか?)
于 2013-04-04T10:18:19.153 に答える
0

列挙型を制御し、それが連続していることを確認できる場合は、次のことを実行できますが、明らかに最新の状態に保つ必要があります。

typedef NS_ENUM(NSInteger, BoxType) {
  Speed,
  FPS,
  Altitude,
  Location,
  Accuracy
};

NSString * BoxTypeToString(BoxType boxType)
{
  static NSString *types[] = { @"Speed", @"FPS", @"Altitude", @"Location", @"Accuracy" };
  return types[boxType];
}

注意

クラスが列挙型を文字列に変換する方法を知る責任を負う正当な理由を与える多くのシナリオを本当に想像できないので、これを別のC関数にしました:/

于 2013-04-04T10:09:17.013 に答える