LoginSignup
26
20

More than 5 years have passed since last update.

UITableView の Section を Swift の enum を使って安全に記述する方法

Posted at

環境

  • Xcode 7.3
  • Swift 2.2
  • そんなに新しい機能は使ってないので特に気にしないでください

背景

UITableView の Section は Int なので switch case で網羅性をチェックできないので仕様変更に変更に弱いのが悩みの種です。

例えば以下のコードだと section == 0 ってどんな Section だっけ? ってなったり、 default を使っているので仕様変更で section == 2 が追加された時に記述漏れが発生したりします。

人間がこの辺を把握するのは辛いので可能であればコンパイル時に Section の追加漏れがあるよ!ってことを警告(もしくはエラー)して欲しいです。

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        switch section {
        case 0:
            return 3
        case 1:
            return 4
        default:
            return 0
        }
    }

そこで Swift の enum の出番

PlayGround のコードを Gist に貼り付けておきました。

動かしてみたい人は以下のコマンドを実行してダウンロードできますので試してみてください。

curl https://gist.githubusercontent.com/mironal/d640c57e06ce2f644137e8dc182e1256/raw/622a731be4e695fe2c7194eb579e7e600e3a3fe9/UITavlewViewSection.swift > UITablewViewSection.playground

動かすとこんな感じの UITableView が表示されます。

image

このコードで重要なのは以下の2箇所ぐらいです。

大事な所1
enum Section: Int {
    case Animals = 0
    case Foods
}
大事な所2
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        switch Section(rawValue: section) {
        case .Some(.Animals):
            return animals.count
        case .Some(.Foods):
            return foods.count
        case .None:
            return 0
        }
    }

大事な所1

大事な所1で Int の enum を定義して、それぞれのセクションに名前をつけています(今回は Animals と Fools)。

このようにすることでまず Int の section を enum の Section に変換できるのでより安全にプログラミングできるようになります。

何が安全なのかといいますと次の説明でわかります。

大事な所2

そして、大事な所2で UITableView の delegate に渡される Int の section を enum の Section に変換して switch case しています。

このように Int ではなく enum で switch することで enum の種類が増えた場合、例えば :beer: が追加してみます。

🍺追加
enum Section: Int {
    case Animals = 0
    case Foods
    case 🍺
}

すると以下の様な感じでエラーが出ます。

switch must be exhaustive... -> switch は網羅的でなければなりません...

といった具合にコンパイル時に switch の case に漏れがあるということをえ教えてくれています。

もちろんエラーが発生しているのでこのプログラムは実行できません。

間違ったプログラムが実行できないので 安全 なのです。

image

余談ですが、 Objective-C で enum を作ってキャストしてから switch case すると似たようなことは出来ますが、未定義な case の値(swift の場合は None になるパターン)があった場合、コンパイル時に検出はできず実行時にクラッシュしますので若干安全ではないです。

悩み

セルを返す delegate (func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell )では戻り値が UITableViewCell? ではなく UITableViewCell なので未定義な section が渡された場合どのように処理すると綺麗なのかが悩ましい(場合によるだろうけど..)

今回の場合は面倒だから基本的にクラッシュするようにしてる。

まとめ

Swift では UITableView の Section を enum で定義することでわりと安全にプログラムすることができる。

26
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
20