Swift で enum を扱う際にハマった問題です。確認は Xcode6 beta4 で行っています。

Swift の enum は AnyObject 型変数に代入できない

Swift では enumAnyObject 型の変数に入れることができません。コンパイルエラーになります。Any 型なら代入できます。

1
2
3
4
5
6
7
8
9
10
11
enum SomeType: Int {
    case None = 0
    case Something
}

let something = SomeType.None
something                                     // Enum Value

let anything: AnyObject = SomeType.Something  // error: type 'SomeType' does not conform to protocol 'AnyObject'

let any: Any = SomeType.Something             // Enum Value

Swift の enumAnyObject protocol を実装していないので、AnyObject 型の変数に入れることが出来ません。

ReactiveCocoa とかと組み合わせるときにこまる

これの何が不便かというと、enum は UIKit でよく使われていて、ReactiveCocoa を Swift で使う際に enum で設定する例えば UITableViewCellAccessoryType なんかを使いたい場合にコンパイルエラーになってしまいます。

1
2
3
4
5
6
7
8
9
// これはコンパイルエラーになる
RAC(self, "cell.accessoryType") = RACObserve(self, "viewModel.checked").map { ($0 as Bool) ? UITableViewCellAccessoryType.Checkmark : UITableViewCellAccessoryType.None }

// こうしないといけない。。
RACObserve(self.viewModel, "checked")
    .subscribeNext { [weak self] arg in
        let checked = arg as Bool
        self!.accessoryType = checked ? .Checkmark : .None
}

既存の Objective-C ライブラリで id が使われている箇所が、Swift では AnyObject に対応するので、 Closure 等で id を引数に取ったり、id を戻り値にしていたりする箇所が AnyObject になってしまい、 enum を利用することができません。

変数に代入するだけなら Any 型にすればいいんですが、既存ライブラリとの連携では難しそうです。 1 これ、何かやり方ないんでしょうかね。。ReactiveSwift 待ちかなぁ


  1. Any 型にすれば代入できることを @takabosoft さんに教えてもらいました。ありがとうございます!