読者です 読者をやめる 読者になる 読者になる

そーす

福岡在住のプログラマ

UITableViewCellの再利用するIDの管理を考える

Swift iOS Extension

f:id:saburesan:20160427075732p:plain すべてのCellをUITableViewCellのサブクラスで実装するときの話です。

UITableViewでCellの再利用をするときって以下の様な感じですよね。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if let cell =  tableView.dequeueReusableCellWithIdentifier("Cell1") as? Cell1 {
            return cell
        } else {
            return Cell1(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell1")
        
        }
    }

個人的に微妙だと思う所

  • Cellの再利用するためのIDに"Cell1"という文字列をハードコーディングしてる
  • as? Cell1 にキャストしてる

です。

まず、ハードコーディングでのミスを減らすためにidtentifierを変数に入れます

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell1Identifier = "Cell1"
        if let cell =  tableView.dequeueReusableCellWithIdentifier(cell1Identifier) as? Cell1 {
            return cell
        } else {
            return Cell1(style: UITableViewCellStyle.Default, reuseIdentifier: cell1Identifier)
        
        }
    }

次に、identifierとCell1というクラスには今のところ関係が無いので

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell1Info: (String, NSObject.Type) = ("Cell1", Cell1.self)
        if let cell =  tableView.dequeueReusableCellWithIdentifier(cell1Info.0) as? cell1Identifier.1 {
            return cell
        } else {
            return Cell1(style: UITableViewCellStyle.Default, reuseIdentifier: cell1Info.0)
        }
    }

なら関係性を持てますが、これはコンパイルエラーです。

結論

ここに落ち着きました。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCellWithType(Cell1) {
            return cell
        } else {
            return Cell1()
        }
    }

UITableViewCellのサブクラスの実装

UITableViewのサブクラスの初期化を以下のようにします

class Cell1: UITableViewCell {
    convenience init() {
        self.init(style: UITableViewCellStyle.Default, reuseIdentifier: NSStringFromClass(Cell1))
        ...

クラス名を再利用Identifierとして持つようにします。

UITableViewを拡張

クラスを引数に指定できるメソッドを追加します。

extension UITableView {
    func dequeueReusableCellWithType<CellType: UITableViewCell>(type: CellType.Type) -> CellType? {
        return dequeueReusableCellWithIdentifier(NSStringFromClass(type)) as? CellType
    }
}

クラス名をIdentifierにしているのでクラス名がわかれば再利用IdentifierとCellのクラスもわかるので毎回キャストを書く必要もなくなりました。

まだiOS初めて2週間くらいなのですが、長年やってる方ってどうやって管理してるだろなぁ