標準のUITableViewのEditModeでどんなことができるのか調べてみました。

あーだこーだ独自の実装をするより、用意されているものを使った方がユーザーさんもわかりやすいかと思います。

今回試してみたのはUITableViewCellの追加、削除、移動の3つです。

こんな感じになります。

UITableView EditMode Sample

ソースコード

すべてViewController.swiftに書いてみました。

ViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var items = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.confirmView()
self.createItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
println(__FUNCTION__)
self.tableView.setEditing(editing, animated: animated)
}
// MARK: IBAction
@IBAction func pushAddBtn(sender: AnyObject) {
let item = self.getCurrentTimeStr()
self.items.addObject(item)
let newIndexPath = NSIndexPath(forRow: self.items.count-1, inSection: 0)
self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: UITableViewRowAnimation.Left)
}
// MARK: Private Method
func confirmView() {
self.navigationItem.leftBarButtonItem = self.editButtonItem()
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.tableFooterView = UIView(frame: CGRectZero)
}
func getCurrentTimeStr() -> String {
let date = NSDate()
let formatter = NSDateFormatter()
formatter.timeStyle = .LongStyle
return formatter.stringFromDate(date)
}
func createItem() {
let currentTimeStr = self.getCurrentTimeStr()
self.items.addObject(currentTimeStr)
}
// MARK: UITableView DataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
let item = self.items[indexPath.row] as String
cell.textLabel?.text = item
return cell;
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
self.items.removeObjectAtIndex(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
default:
return
}
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// MARK: UITableView Delegate
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
let item: AnyObject = self.items[sourceIndexPath.row]
self.items.removeObjectAtIndex(sourceIndexPath.row)
self.items.insertObject(item, atIndex: destinationIndexPath.row)
}
}

とこのようなソースコードになりました。

SwiftObjective-Cもほぼほぼ変わらないので、うまく読み替えてもらえればと思います。

では機能毎に紹介していきます。

UITableViewCellの追加

追加は以下の部分で行っています。

1
2
3
4
5
6
7
// MARK: IBAction
@IBAction func pushAddBtn(sender: AnyObject) {
let item = self.getCurrentTimeStr()
self.items.addObject(item)
let newIndexPath = NSIndexPath(forRow: self.items.count-1, inSection: 0)
self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: UITableViewRowAnimation.Left)
}

ちなみにこの処理は自分で追加します。

ボタンを設置して、IBActionで実行するイメージです。

getCurrentTimeStr()で現在時間のStringを取得してそれをまず配列(self.items)の最後に追加しています。

その後NSIndexPathを作成して、self.tableViewに追加するようにメッセージを送っています。

例えば一番最初に追加したい場合は

1
2
3
4
let newIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let item = self.getCurrentTimeStr()
self.items.insertObject(item, atIndex: newIndexPath.row)
self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: UITableViewRowAnimation.Left)

という様に追加します。

追加のアニメーションはinsertRowsAtIndexPaths(_:withRowAnimation:)withRowAnimationで指定してます。

UITableViewCellの追加

ここからUITableViewの標準機能を使います。

順を追って説明します。

編集ボタンを実装する

EditボタンはUIViewControllereditButtonItem()を使ってます。

今回の例だとnavigationItem.leftBarButtonItemにセットしています。

このボタンを押すとUIViewControllersetEditing(editing: Bool, animated: Bool)が呼ばれるのでこれをOverrideします。

そしてUITableViewsetEditingを呼びます。

1
2
3
4
5
6
7
override func viewDidLoad() {
self.navigationItem.leftbarButtonItem = self.editButtonItem()
}
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.setEditing(editing, animated: animated)
}

これで編集画面になります。

移動させる処理を実装する

UITableViewDataSourceUITableViewDelegateを実装している前提でお話します。

以下のメソッドを追加してください。

1
2
3
4
5
6
7
8
9
10
11
// MARK: UITableView DataSource
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// MARK: UITableView Delegate
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
//
}

この2つを実装しないと編集時にCellの右側に3本線が表示されません。

編集時に表示される3本線をドラッグ&ドロップでCellを移動することが出来ます。

移動が完了した時にfunc tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath){}が呼ばれます。

例えばこんな処理になるかと思います。

1
2
3
4
5
6
7
8
// MARK: UITableView Delegate
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
// sourceIndexPath: 元の場所のIndexPath
// destinationIndexPath: 新しい場所のIndexPath
let item: AnyObject = self.items[sourceIndexPath.row]
self.items.removeObjectAtIndex(sourceIndexPath.row)
self.items.insertObject(item, atIndex: destinationIndexPath.row)
}

こんな感じで所持しているデータも移動します。

これで移動に関する処理は完了です。

UITableViewCellの削除

ここもUITableViewの標準機能を使います。

編集ボタンはUITableViewCellの移動と同じです。

ここでは削除の実装だけ説明します。

削除する処理を実装する

以下の処理を実装してください。

1
2
3
4
5
6
// MARK: UITableView DataSource
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
//
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {}

これで編集ボタンを押すと削除ボタンが表示されると思います。

削除の処理は以下のようになります。

1
2
3
4
5
6
7
8
9
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
self.items.removeObjectAtIndex(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
default:
return
}
}

という様になるかと思います。

UITableViewdeleteRowsAtIndexPaths(_:, withRowAnimation:)Cellの削除のアニメーションをしています。

これで削除も実装完了です。

終わりに

出来る限り標準にある機能を使った方がユーザーさんもわかりやすいと思います。

とっても便利で実装しやすいと思うので独自実装している人は修正した方がいいかなと思います。

以上です。

参考

UITableView: Deleting, Moving, and Viewing Rows

UITableViewDataSource Protocol Reference

iOS

「iOS」のおすすめ記事