【Swift】テーブルに表示しているデータをキーボードを使って変更する。(Swift 2.1、XCode 7.2)
テーブルデータの変更とは
前回までの記事で、TableView(以下、テーブルビュー)とTableViewCell(以下、セル)を使ってデータを目次のように並べて表示し、セルの並び替え、削除を行う方法を説明してきた。⇒「記事」
「削除ができる。」、「並び替えができる。」、その他に必要そうなのはテーブルに表示しているデータをキーボードを使って変更する機能だ。そこで本記事では、キーボードからセルと元データの値を変更する実装方法について説明する。なお、今まで説明してきた内容の復習なので難しく考えなくても大丈夫。
テーブルデータ変更の仕様を考える
まずどんなテーブルビューを作るか考える。セルをタップすると下図のようにキーボードが表示され、タップしたセルの文字列を自由に変更できるようにする。そして、キーボードが閉じた段階で元データが変更内容で上書きされる仕様にする。
コードを把握しやすくするため、セルの並び替えや削除機能は実装しない。
実装は前回の記事で作成したものを修正する流れで行うので、前回の記事をまだ読んでいない方はそちらを試したあとにここから先を読むことをお勧めする。⇒「前回の記事」
テーブルデータの変更を実装する
それでは作業を開始する。
XIBファイルの画面を開き、配置していた3個のラベルをすべて削除する。そして、UITextField(以下、テキストフィールド)の部品を新たに配置する(下図赤矢印)。
次に、テキストフィールドをクリックしたあとに黄緑枠のアトリビュートインスペクタボタンを押して設定画面を開き、Border Styleの設定を変更してテキストフィールドの枠線を消す。
次にTestTableViewCell.swiftを開き、前回の記事で追加したラベル(@Outlet)の3行を削除する。続いて、Ctrlキーを押しながらテキストフィールドをソースコードにドラッグ&ドロップで運び、吹き出しの設定画面を開く。Connectionに「Outlet」、Nameに「testTextField」を入力し、Connectボタンを押す。
テキストフィールドの値が修正されてから元データを変更するまでの流れはデリゲートを利用して実装する。⇒「デリゲートとは」
下図のように、テキストフィールドの変更通知を自作セルが受け、自作セルがUIViewControllerインスタンスに通知を流す。そして、UIViewControllerインスタンスは自分が保持している元データを修正するという実装にする。
自作セルのソースコード(TestTableViewCell.swift)を開き、以下のように修正する。テキストフィールドのデリゲート先に自作セルがなり、通知を受けたらキーボードを閉じて自分のデリゲート先に通知を流している。
また、自分のデリゲート先(ViewControlloerクラス)に適用してもらうプロトコル(TestDelegate)をここで定義している。
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 |
// // TestTableViewCell.swift // import UIKit //デリゲート先に適用してもらうプロトコル protocol TestDelegate { func textFieldDidEndEditing(cell:TestTableViewCell, value:String) } class TestTableViewCell: UITableViewCell, UITextFieldDelegate { @IBOutlet weak var testTextField: UITextField! var delegate:TestDelegate! = nil //最初からある初期化メソッド override func awakeFromNib() { super.awakeFromNib() //テキストフィールドのデリゲート先を自分に設定する。 testTextField.delegate = self } //最初からあるメソッド override func setSelected(selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) } //デリゲートメソッド func textFieldShouldReturn(textField: UITextField) -> Bool { //キーボードを閉じる。 textField.resignFirstResponder() return true } //デリゲートメソッド func textFieldDidEndEditing(textField: UITextField) { //テキストフィールドから受けた通知をデリゲート先に流す。 self.delegate.textFieldDidEndEditing(self, value:textField.text!) } } |
次にViewController.switを開き、以下のように修正する。データを返すメソッドで自作セルのデリゲート先に自分を設定している。通知を受けたら変更されたセルのインデックスを取得し、データを修正している。
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 |
// // ViewController.swift // import UIKit class ViewController: UIViewController,UITableViewDataSource, TestDelegate { @IBOutlet weak var testTableView: UITableView! //データ var dataList = ["青山","阿部","加藤","神田","佐藤","坂田"] //データを返すメソッド func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell { //セルを取得して値を設定する。 let cell = tableView.dequeueReusableCellWithIdentifier("TestCell", forIndexPath:indexPath) as! TestTableViewCell cell.testTextField.text = dataList[indexPath.row] //自作セルのデリゲート先に自分を設定する。 cell.delegate = self return cell } //データの個数を返すメソッド func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int { return dataList.count } //最初からある初期化メソッド override func viewDidLoad() { super.viewDidLoad() //自作セルをテーブルビューに登録する。 let testXib = UINib(nibName:"TestTableViewCell", bundle:nil) testTableView.registerNib(testXib, forCellReuseIdentifier:"TestCell") } //デリゲートメソッド func textFieldDidEndEditing(cell: TestTableViewCell, value:String) { //変更されたセルのインデックスを取得する。 let index = testTableView.indexPathForRowAtPoint(cell.convertPoint(cell.bounds.origin, toView:testTableView)) //データを変更する。 dataList[index!.row] = value print(dataList) } } |
以下は実際の動画
標準出力には以下のように表示される。
1 2 |
["青山", "阿部", "加藤", "神田", "テスト", "坂田"] |