タイトル 

 enumの注意点 一番目の値は =1

enum をインスタンスの属性として使うとき注意が必要だったので忘れないようにメモ。

サンプル 確認バージョン: iOS 5.1

問題:インスタンスが nil でも if分岐に入ってくる

再現:

enumをインスタンスの属性としてこんな感じで用意する

Tシャツとそのサイズというのをクラスとして書いてみた。

typedef enum {

    S, M, L, XL

} SIZE;

@interface Tshirts : NSObject

@property SIZE size;

@end

@implementation Tshirts

@synthesize size;

@end

このクラスを使って if文を書いてみる。

    Tshirts *shirts;

    if (shirts.size == S) {

        

        //tester nil でも、ここを通る。

        NSLog(@”ifの中 shirts=%@ なのに, shirts);

    }

shirts はまだ nil なので、if の中身は、 nil == S となるため、

直感的には、if の中に入らないで通過してほしいところ、

ログを確認してみると、

ifの中 shirts=(null) なのに

と分岐の中に入ってしまう。

これはどういうことなのかというと、SIZE S の値は 0 だから。

比較を行った場合、nil == 0 は YES になるからです。

試しに、こんな感じで書いてみます。

    

    NSLog(@”%d”, S);

    if (nil == 0) {

        NSLog(@”nil == 0 なのです。);

    }

実行してみると、

0

nil == 0 なのです。

というログが出てきます。

コレをさけるためには、

1. enum に 0 が無いようにする

2. enum の頭に None の様なダミーをセットする

でしょうか。

typedef enum {

    S = 1, M, L, XL

} SIZE;

こんな感じで、定義すれば良いと思います。

比較する方もこんな感じで書き換えて試してみましょう。

    // enum 比較

    Tshirts *shirts;

    if (shirts.size == S) {

        

        //tester nil でも、ここを通る。

        NSLog(@”ifの中 shirts=%@ なのに, shirts);

    } else {

        NSLog(@”通らなくなりました。);

    }

    

    NSLog(@”S:%d, M:%d, L:%d, XL:%d”, S, M, L, XL);

ログにはこう出てきました。

通らなくなりました。

S:1, M:2, L:3, XL:4

 

これで、インスタンスがnilの時を考慮しないですみます。

参考)

今回は、Single View Application の ViewController.m で試していました。

ファイルにこんな感じで書くと簡単に確認できます。

#import “ViewController.h”

#import “MySingleton.h”

typedef enum {

    S = 1, M, L, XL

} SIZE;

@interface Tshirts : NSObject

@property SIZE size;

@end

@implementation Tshirts

@synthesize size;

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    // enum 比較

    Tshirts *shirts;

    if (shirts.size == S) {

        

        //tester nil でも、ここを通る。

        NSLog(@”ifの中 shirts=%@ なのに, shirts);

    } else {

        NSLog(@”通らなくなりました。);

    }

    

    NSLog(@”S:%d, M:%d, L:%d, XL:%d”, S, M, L, XL);

}

@end