Objective-c の typedef を文字列に相当するものに変換する

これは実際には C に関する質問であり、Objective-C (C 言語のスーパーセット) に固有のものではありません。 C の列挙型は整数として表されます。したがって、列挙値を指定して文字列を返す関数を作成する必要があります。これを行うには多くの方法があります。列挙値を配列またはマップ構造へのインデックスとして使用できるような文字列の配列 (例:NSDictionary ) 列挙型の値を文字列にマップしますが、これらのアプローチは、変換を明示的にする関数ほど明確ではないことがわかりました (および配列のアプローチですが、古典的な C は 列挙値が 0 から連続していない場合は危険です)。このようなものがうまくいきます:

- (NSString*)formatTypeToString:(FormatType)formatType {
    NSString *result = nil;

    switch(formatType) {
        case JSON:
            result = @"JSON";
            break;
        case XML:
            result = @"XML";
            break;
        case Atom:
            result = @"Atom";
            break;
        case RSS:
            result = @"RSS";
            break;
        default:
            [NSException raise:NSGenericException format:@"Unexpected FormatType."];
    }

    return result;
}

列挙値の正しい構文に関する関連する質問は、値のみを使用することです (例:JSON )、FormatType.JSON ではありません 構文。 FormatType タイプと列挙値 (例:JSONXML など) は、その型に割り当てることができる値です。


簡単にはできません。 C と Objective-C では、enum は実際には単なる美化された整数定数です。名前のテーブルを自分で生成する必要があります (または、プリプロセッサを悪用して)。例:

// In a header file
typedef enum FormatType {
    JSON,
    XML,
    Atom,
    RSS
} FormatType;

extern NSString * const FormatType_toString[];

// In a source file
// initialize arrays with explicit indices to make sure 
// the string match the enums properly
NSString * const FormatType_toString[] = {
    [JSON] = @"JSON",
    [XML] = @"XML",
    [Atom] = @"Atom",
    [RSS] = @"RSS"
};
...
// To convert enum to string:
NSString *str = FormatType_toString[theEnumValue];

このアプローチの危険性は、列挙型を変更した場合、名前の配列を変更することを覚えておく必要があることです。この問題は、プリプロセッサを悪用することで解決できますが、扱いにくく醜いものです。

また、これは有効な列挙型定数があることを前提としていることにも注意してください。信頼できないソースからの整数値がある場合は、定数が有効であることをさらに確認する必要があります。列挙型に「過去の最大」値を含めるか、配列の長さ sizeof(FormatType_toString) / sizeof(FormatType_toString[0]) 未満かどうかを確認します .


私の解決策:

編集:最新の Obj-C を使用して、最後にさらに優れたソリューションを追加しました

1.
名前をキーとして配列に入れます。
インデックスが適切な列挙型であり、正しい順序であることを確認してください (それ以外の場合は例外)。
注:名前 *_names*; として合成されたプロパティです。

コードのコンパイルはチェックされませんでしたが、アプリで同じ手法を使用しました。

typedef enum {
  JSON,
  XML,
  Atom,
  RSS
} FormatType;

+ (NSArray *)names
{
    static NSMutableArray * _names = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _names = [NSMutableArray arrayWithCapacity:4];
        [_names insertObject:@"JSON" atIndex:JSON];
        [_names insertObject:@"XML" atIndex:XML];
        [_names insertObject:@"Atom" atIndex:Atom];
        [_names insertObject:@"RSS" atIndex:RSS];
    });

    return _names;
}

+ (NSString *)nameForType:(FormatType)type
{
    return [[self names] objectAtIndex:type];
}


///

2.
Modern Obj-C を使用すると、辞書を使用して説明を列挙型のキーに関連付けることができます。
順序は関係ありません .

typedef NS_ENUM(NSUInteger, UserType) {
    UserTypeParent = 0,
    UserTypeStudent = 1,
    UserTypeTutor = 2,
    UserTypeUnknown = NSUIntegerMax
};  

@property (nonatomic) UserType type;

+ (NSDictionary *)typeDisplayNames
{
    return @{@(UserTypeParent) : @"Parent",
             @(UserTypeStudent) : @"Student",
             @(UserTypeTutor) : @"Tutor",
             @(UserTypeUnknown) : @"Unknown"};
}

- (NSString *)typeDisplayName
{
    return [[self class] typeDisplayNames][@(self.type)];
}


使用法 (クラス インスタンス メソッド内):

NSLog(@"%@", [self typeDisplayName]);