ProMotion::TableScreenでViewCellにviewを追加する方法

ProMotion::TableScreenでは、デフォルトでTableViewで使うデータに追加したいviewをsubviewsというキーで含めておけば追加してくれます。

class MyScreen < ProMotion::TableScreen

  def table_data
    @table_data = [
      cells: [
        { title: 'cell 1', subviews: [label_1_1, label_1_2] },
        { title: 'cell 2', subviews: [label_2_1, label_2_2] },
      ]
    ]
  end
end

label_1_1 label_1_2 等はViewCell中での表示位置や表示内容などを設定済み。
こうすることで、PM::TableScreenがcellを作成する際に、subviewsから追加するviewを拾ってaddSubviewしてくれます。

しかもdequeuereusablecellwithidentifierでcellが再利用される際、(度々大抵の人が陥るであろう)"再利用される前にaddSubviewされているview" あるいは "多重にaddSubviewしてしまう" 問題についても、PM::TableScreenがうまくremoveFromSuperviewしてから再度addSubviewしてくれるので安心です。

ProMotion gem すばらしい


しかし、cellへ追加したいviewのコードがScreen(ViewController)に書かなくてはいけないため、自分のコードが"糞コードの海"に沈みかねません。

そこでProMotionでは ProMotion::TableViewCell というUITableViewCellを継承してProMotionでViewCellをうまく扱うためのmoduleをincludeしたクラスが用意されてます。

例に、title(textLabel)もsubtitle(detailLabel)も使ってしまっているので、一つlabelを追加してcountを表示するViewCellを作ってみることにしましょう

今回はtable_dataのcellsにはsubviewsは使わずに、cell_classとcell_styleを追加し、それぞれ作成したMyTableViewCellとsubtitleを使うのでUITableViewCellStyleSubtitleを設定します。
あとは、MyTableVlewCellでsetupメソッドを上書きしてsuperを呼んでデフォルトの初期化処理をさせつつ、追加したいviewを準備した後に再度setup_subviewsを呼びます。

class MyScreen < ProMotion::TableScreen

  def table_data
    @table_data = [
      cells: [
        { title: 'cell 1', subtitle: 'sub title 1', count: 100, cell_class: MyTableViewCell, cell_style: UITableViewCellStyleSubtitle, },
        { title: 'cell 1', subtitle: 'sub title 1', count: 0, cell_class: MyTableViewCell, cell_style: UITableViewCellStyleSubtitle, },
      ]
    ]
  end
end

class MyTableVlewCell < ProMotion::TableViewCell

  attr_accessor :count

  def setup(data_cell, screen)
    super # super呼んで本来の初期化処理とかさせる1度目のset_subviewsも呼ばれる

    count_label = UILabel.new.tap do |label|
      # frameとかfontとか略
      l.text = self.count
    end
    data_cell[:subviews] = [count_label] # data_cellはtable_dataのcellsの配列が1つ入ってる感じ
    set_subviews # 2度目のset_subviews

    self
  end
end

この方法だと、"data_cell[:subviews] が(nilなので実質処理されないけど)、superにより1度に無駄に呼ばれる" などの無駄っぽい処理がありますが、ViewCellに関する処理が1カ所にまとめられるのは利点じゃないでしょうか。

以上、ProMotionのwikiにも書かれていないsubviewの追加方法でしたー