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

UITableView 編集時に挿入用の行を表示したい

UITableView 編集時のみ、挿入用の行を表示したい。こんなやつ。

f:id:griefworker:20140513201354p:plain

アイコン自体は tableView:editingStyleForRowAtIndexPath で UITableViewCellEditingStyleInsert を返せば表示できる。 ただ、編集時のみ挿入用の行を表示するとなると、結構面倒だった。

以下、RubyMotion でのサンプルコード。

# coding: utf-8

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.rootViewController = MasterViewController.controllerWithNavigation
    @window.makeKeyAndVisible
    true
  end
end

class MasterViewController < UITableViewController
  CELL_ID = "cell-id"

  def self.controllerWithNavigation
    UINavigationController.alloc.initWithRootViewController(
      self.alloc.initWithStyle(UITableViewStylePlain)
    )
  end

  def items
    @items ||= [
      { title: "foo" },
      { title: "bar" },
    ]
  end

  def viewDidLoad
    super
    self.title = "Sample"
    self.navigationItem.rightBarButtonItem = self.editButtonItem
  end

  def tableView(tableView, numberOfRowsInSection:section)
    if self.isEditing
      # 編集中は追加行を表示するので行数 +1 する
      self.items.size + 1
    else
      self.items.size
    end
  end

  def tableView(tableView, cellForRowAtIndexPath:indexPath)
    cell = tableView.dequeueReusableCellWithIdentifier(CELL_ID) ||
      UITableViewCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier: CELL_ID)
    
    if self.isEditing and
      indexPath.row >= self.items.size
      # 追加行のとき
      cell.textLabel.text = "追加"
    else
      item = self.items[indexPath.row]
      cell.textLabel.text = item[:title]
    end

    cell
  end

  def setEditing(editing, animated:animated)
    super

    # 追加行の IndexPath を求める
    row = self.items.size
    indexPath = NSIndexPath.indexPathForRow(row, inSection:0)

    # 追加行の挿入/削除
    self.tableView.beginUpdates
    if editing
      self.tableView.insertRowsAtIndexPaths(
        [indexPath],
        withRowAnimation:UITableViewRowAnimationFade
      )
    else
      self.tableView.deleteRowsAtIndexPaths(
        [indexPath],
        withRowAnimation:UITableViewRowAnimationFade
      )
    end
    self.tableView.endUpdates
  end

  def tableView(tableView, didSelectRowAtIndexPath:indexPath)
    if self.isEditing
      if indexPath.row < self.items.size
        # 編集ページに移動
      else
        # [追加] をタップしたので追加ページに移動
      end
    else
      # 詳細を表示
    end
  end

  def tableView(tableView, editingStyleForRowAtIndexPath:indexPath)
    if indexPath.row < self.items.size
      UITableViewCellEditingStyleDelete
    else
      # [追加] 行には + アイコンを表示
      UITableViewCellEditingStyleInsert
    end
  end
end

UITableView のプロパティ一発で出来るようになったらいいんだけど。