Objective-CのenumをSwiftで使うときは、値がEnumValueになるのでちょっと注意
この記事は、仙台iOS開発者勉強会(SWWDC) Advent Calendar 2014 10日目の記事です。
Objective-CのenumをSwiftで使うときのちょっとしたTips
今回の元ネタは、先日のAdvent Calendar対策もくもく会にて出た質問です。多分他にも困る人がいるのではないかと思いまして。
まず、下記のようなenumがあります。これをbridge-headerを経由して、Swiftで使います。
typedef NS_ENUM(NSUInteger, EnumValue) { EnumValue1 = 0x00000001, EnumValue2 = 0x00000002, EnumValue3 = 0x00000004, EnumValue4 = 0x00000008, };
そして、Objective-Cのif文をそのままSwiftに移植したら、ビルドエラーになるとのことでした。
if EnumValue.Value1 & EnumValue.Value2 { println("これはビルドエラー") } // Cannot Invoke '&' with an argument list of type'(EnumValue, EnumValue)'
enumの元の値を取得するときは、"rawValue"
エラーメッセージを見ると、「EnumValueとEnumValueの&は出来ないよ」というようなことを言われています。 Objective-CならEnumValue1 もEnumValue2 も”NSUInteger"だったので &で演算ができていたのですが、Swiftに持ってくるとEnumValueになっちゃうようですね。
こんな時は、"rawValue"を使うと、元の値がとれます。
// 値出力テスト println("EnumValue.Value1=\(EnumValue.Value1)") println("EnumValue.Value1.rawValue=\(EnumValue.Value1.rawValue)") // 実行結果(print) EnumValue.Value1=(Enum Value) EnumValue.Value1.rawValue=1
さらに、if文の書き方にも注意。
では、rawValueを使用して下記のように書くと、ビルドエラーが起きます。
if EnumValue.Value1.rawValue & EnumValue.Value2.rawValue { println("これもビルドエラー") } // Type 'UInt' does not conform to protocl 'BooleanType'
これは以前アドヴェントCalendarで取り上げた問題ですね.([ Swiftのif文の条件部は、BooleanType準拠の値しか受け付けない模様 - Qiita] )。Swiftでは、条件式の中身はBooleanTypeになっていないといけないのでした。
更に修正を加え、最終的にはこんな感じになりました。
if EnumValue.Value1.rawValue & EnumValue.Value2.rawValue != 0 { println("これはok") }
終わりに
Swiftで書くと、こういう「地味にObjective-Cのソースコードを移植する」作業が発生するので、時間を取られてしまうんですよね。
なので、こういったTips記事を書いていって、調査の負担を減らして行けば、Swiftがより普及するのではないかなと思いました。