Swiftのoptional funcでenumを使いたい時
protocolについて
まずswiftにはprotocolが用意されている。例えばUIKit
系のクラスではよくdelegateやdataSourceが用意されていて、他のクラスに処理を委譲する設計になっている。delegateやdataSourceを継承したクラスはその処理を書かなければならない。
class HogeViewController: UIViewController, UITableViewDataSource { // UITableViewDataSource内で定義された関数をこのクラス内で実装しなければいけない // 実装しなければコンパイルエラーが起こる func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {} func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} }
optional funcを定義する
上でprotocolについて説明したが、継承しても実装しなくても大丈夫なようにもできる。optional
を修飾子としてつければ良い。
// optional funcを定義するにはそれとprotocolに@objc属性をつけなければいけない @objc protocol HogeDelegate { @objc optional func doSomething() }
optional funcにenumを使う
通常のprotocol(@objc
属性がついてない)ものであればenumを使ってもエラーにはならないが、@objc
属性がついているものはエラーになってしまう。
enum MyType { case A case B } @objc protocol HogeDelegate { @objc optional func didChange(type: MyType) // Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C }
これの解決策はenumにも@objc
属性をつける。ただし、注意点としてそのenumにはInt
を継承させなければいけない。
@objc enum MyType: Int { case A case B } @objc protocol HogeDelegate { @objc optional func didChange(type: MyType) }
まとめ
optional funcにenumを使いたければ、protocolとenumに@objc
属性をつければ良い。
コード例は抽象的だが、自分でカスタムUIクラスなど作るときに使えると思う。
最後にswiftにはenumやprotcolといった魅力的な機能があるが、それにわざわざ@objc
属性を付けるのは少し面倒くさいと思ってしまった。