作ってみたらわりといい感じだったので共有
#やりたいこと
1.セクション名、セル名をenumで完全に管理する
2.switchやifをネストさせず、また数値を使わずにenumで分岐したい
3.UITableViewで使うのでセクション数とセクションごとのセル数を取得したい
4.不正なindexPathはguardしたい
#前提
Swift2.3
このようなUITableViewをenumで管理してみます。
##やってみた
まずはenumのカウントを出来るようにしたり、管理用のプロトコルを定義する。
なくてもいいけど、セクションやローを増やしたり減らしたりする時に弄る箇所が少なくなるし、見通しもいいので定義しておきましょう。
//カウント可能なenum拡張
protocol Countable { }
extension Countable where Self : RawRepresentable, Self.RawValue == Int {
static func count() -> Int {
var count = 0
while let _ = Self(rawValue: count) { count += 1 }
return count
}
}
//ローとセクション用にプロトコルを分ける
protocol IndexRow: Countable { }
protocol IndexSection: Countable { }
次にメインのenumの実装です。
Sectionに管理するセクション一覧を、Rowには一覧とセクションごとの処理を追加します。
Rowにまとめるのは見通しを良くするためなので、不要であれば外に出しても良いです。
また、セクション名とRow.Hogehogeの名前も一緒である必要はありません。
import UIKit
//セクションの管理enum
enum Section: Int, IndexSection {
case Instruments
case UiAnimation
case Network
case Iad
//セクションごとのロー数を返す
func rowCount() -> Int {
switch self {
case .Instruments: return Row.Instruments.count()
case .UiAnimation: return Row.UiAnimation.count()
case .Network: return Row.Network.count()
case .Iad: return Row.Iad.count()
}
}
}
//ローの管理enum
enum Row {
enum Instruments: Int, IndexRow {
case Logging
}
enum UiAnimation: Int, IndexRow {
case Animation
}
enum Network: Int, IndexRow {
case Status
}
enum Iad: Int, IndexRow {
case FillRate
case AdRefreshRate
case Hightlight
case Unlimited
}
//セクションに対応するロー要素を返す
static func create(section: Section, rowIndex: Int) -> IndexRow? {
switch section {
case .Instruments: return Instruments(rawValue: rowIndex)
case .UiAnimation: return UiAnimation(rawValue: rowIndex)
case .Network: return Network(rawValue: rowIndex)
case .Iad: return Iad(rawValue: rowIndex)
}
}
}
最後にNSIndexPathにprivate extensionを生やします
private extension NSIndexPath {
func parse() -> (Section, IndexRow)? {
guard let section = Section(rawValue: section) else { return nil }
guard let row = Row.create(section, rowIndex: row) else { return nil }
return (section, row)
}
}
##使ってみる
実際使ってみます。
//サンプル用のIndexPath
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
//IndexPathから生成、不正の場合はnilが返る
guard let (section, row) = indexPath.parse() else { return }
//セクション名・セル名で分岐
switch (section, row) {
case (Section.Instruments, Row.Instruments.Logging):
break
case (Section.UiAnimation, Row.UiAnimation.Animation):
break
case (Section.Network, Row.Network.Status):
break
case (Section.Iad, Row.Iad.FillRate):
break
case (Section.Iad, Row.Iad.AdRefreshRate):
break
case (Section.Iad, Row.Iad.Hightlight):
break
case (Section.Iad, Row.Iad.Unlimited):
break
default: break
}
//セクション数
let sectionCount = Section.count()
//セクションのセル数
let rowCount = section.rowCount()
さいこうでは…
indexPathの要素だけから生成されたsectionとrowがswitchでキレイに分岐されていきます。
セル数やセクション数も簡単に取れるのでUITableViewでも利用出来そうです。
設定画面などで活躍しそう。
何か改善点あればコメントください!