【Swift4】初心者でも簡単に作れるTodo Listアプリを作ってUITableViewの基本を学ぶ

#**はじめに**
UITableViewの使い方を手っ取り早く学ぶのはTodo Listアプリを作ってみるのが良いんじゃないかなと思ったので、アプリの作り方を紹介しながら解説していこうと思います。

※この記事はUITableViewについて焦点を当てているのでデータベースやデザインパターンなどには触れていません。




#**そもそもUITableViewとは？**
>###**UITableView**
UITableView はiOSのUIフレームワークに含まれる代表的なクラスのひとつで、iOSアプリの開発者にとってはおなじみのものでしょう。これは画面上に一次元のリストを表示するための汎用的なUI部品です。

<省略>

>
iPhone では指での操作が十分に行えるよう、全てのUI要素が大きくデザインされます。そのため（iPhone は当時のほとんどのスマートフォンよりも大きなスクリーンを持っていましたが）情報を段組みで二次元的にレイアウトするよりも、全てを単純な一次元リストにして画面をシンプルに保つことを選択したのです。これは二次元空間を自由に使って情報を提示してきたデスクトップGUIからすれば一種の低次元化ですが、片手で使える情報端末のマテリアルオネスティ（その物の本来的な性質に率直に従うこと）として肯定できるでしょう。iPhone の中でテーブルビューが多用されるのには、そのような正当性があるのです。
テーブルビューの視覚的な特徴としては、画面の端まで伸びたセルの罫線が挙げられます。これによってスクリーンが一次元のリストで占められていることが明示されます。またテーブルビューにはセクションをつくることができ、これは半透明の見出し行として表示されます。秀逸なのは、この見出し行は通常は他のセルとともにスクロールしますが、画面上端まで来るとそこに固定され、次のセクションの見出し行にぶつかるまで表示され続けることです。また画面の右端にはセクションを頭出しするためのインデックスを配置することもできます。このような細かな工夫が、スクロール時の視認性や操作性を向上させています。
多くの情報を一次元のリストで表現すると、その分画面は縦長になります。そのため、スクロールのしやすさは重要なデザイン要件となります。
UITableViewは情報をリストとして表示できるように作られたビューです。
ほとんどのアプリで使われています。

参考) https://www.sociomedia.co.jp/8590

この記事はiPhoneのUIの歴史が詳細に書かれていて、それぞれのViewの役割が大変よく理解できます。
一度時間をかけてじっくりと読んでみることをオススメします。




#**Todo Listアプリを作ろう** 
UITableViewがどんな役割なのかを簡単に理解したところで、早速手を動かしてアプリを作っていきましょう！



##**1. UITableViewControllerを扱う準備**

###**UITableViewControllerを追加**

まず最初にstoryboardにViewControllerを消してUITableViewControllerを追加します。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/1f5f1999-dbf0-5982-9a2f-2bbe4364812b.png)

この際に**→**を移動させることを忘れないでください。




###**ViewControllerの名前を変更**

左にあるファイル名を「ViewController」→「TodoListViewController」に変更。
また、コードの中にある``ViewController``を``TodoListViewController``に、スーパークラスの``UIViewController``の部分も``UITableViewController``に変更します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/dcae2404-03ce-b5ec-8505-b610cfacbbc9.png)




###**storyboardとリンク**

ClassをTodoListViewControllerにします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/f8ea2613-d77b-1c4d-5110-46cd367109b6.png)



###**Identifierの追加**

cellのIdentifierを「ToDoItemCell」にします・

![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/608b52bc-3755-3aff-7ef3-c47cbf2d2019.png)




###**NavigationControllerを追加**###

Editor→Embedin→Navigation Controllerから追加できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/4f9e1d6d-27f8-ad1f-a795-f5b4e90cc559.png)




###**NavigationBarにタイトルを追加**###

好きなタイトルを書いてください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/7095bb40-0866-c553-1f96-aefde7e9fd2e.png)



###**NavigationBarにカラーを追加**###

NavigationBarを選択してタイトルや背景を自分の好きな色に変えてみましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/0a967e35-96cf-b453-3e3c-2d10fe988197.png)




###**NavigationBarにBar Button Itemを追加**###
右下から「Bar Button Item」を探して、「Navigation Bar」の右の部分に追加しましょう。
「System Item」から「Add」を選ぶと「＋」に変わります。
また、カラーもタイトルに合わせて変えてみましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/b30c0aae-9f09-bf49-6a2a-6f60bd9dfd00.png)




##**2. 基本となるTableViewを作成**
```swift:TodoListViewController
import UIKit

class TodoListViewController: UITableViewController {
    
    // アイテムの型
    class Item {
        var title : String
        var done: Bool = false
        
        init(title: String) {
            self.title = title
        }
    }
    
    // この配列に作ったアイテムを追加していく
    var itemArray: [Item] = []

    override func viewDidLoad() {
        
        super.viewDidLoad()
        
        // NaviBarのタイトルを大きく表示させる
        navigationController?.navigationBar.prefersLargeTitles = true
        
        // あらかじめ3つアイテムを作っておく
        let item1: Item = Item(title: "宿題をする")
        let item2: Item = Item(title: "牛乳を買う")
        let item3: Item = Item(title: "手紙を書く")
        
        // 配列に追加
        itemArray.append(item1)
        itemArray.append(item2)
        itemArray.append(item3)
        
    }
    
    
    
    // MARK - セルの数を指定
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return itemArray.count
        
    }
    
    
    
    // MARK - セルのカスタマイズ
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath)
        let item = itemArray[indexPath.row]
        cell.textLabel?.text = item.title
        cell.accessoryType = item.done ? .checkmark : .none
        return cell
        
    }

}
```

これでリストの完成です。
配列の中にあるあたいの数だけセルが表示されます。

セルはメモリの節約のために数個のセルが繰り返し利用されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/259967/37a429c2-01ed-a141-cc62-ab56acfe7e9b.png)




##**3. チェックマーク機能**

```swift:TodoListViewController
// MARK - チェックマーク機能
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // 選択されたセルに実行される処理
        
        let item = itemArray[indexPath.row]
        
        // チェックマーク
        item.done = !item.done
        
        // リロードしてUIに反映
        self.tableView.reloadData()
        
        // セルを選択した時の背景の変化を遅くする
        tableView.deselectRow(at: indexPath, animated: true)
        
    }
```

セルが選択されたアイテムのdoneがfalseならtrueを代入します。
つまりチェックマークが付いていなければチェックマークを追加します。
逆も同じです。


![ezgif.com-gif-to-mp4.gif](https://qiita-image-store.s3.amazonaws.com/0/259967/008f1bba-248a-5425-afc4-eb56bebbd278.gif)

##**4. 新規アイテム追加機能**
```swift:TodoListViewController
 // MARK - 新規アイテム追加機能
    @IBAction func addButtonPressed(_ sender: Any) {
        // プラスボタンが押された時に実行される処理
        
        var textField = UITextField()
        
        let alert = UIAlertController(title: "新しいアイテムを追加", message: "", preferredStyle: .alert)
        
        let action = UIAlertAction(title: "リストに追加", style: .default) { (action) in
            // 「リストに追加」を押された時に実行される処理
            
            let newItem: Item = Item(title: textField.text!)
            
            // アイテム追加処理
            self.itemArray.append(newItem)
            self.tableView.reloadData()
            
        }
        
        alert.addTextField { (alertTextField) in
            alertTextField.placeholder = "新しいアイテム"
            textField = alertTextField
        }
        
        alert.addAction(action)
        present(alert, animated: true, completion: nil)
        
    }

```

まずはstoryboardの「Bar Button Item(＋ボタン)」からTodoListViewControllerにひっぱてきて、``addButtonPressed``という名前のIBActionを作ります。

ボタンを押すと、アラートで入力画面が出るようにし、「リストに追加」が押されるとリストに新しいアイテムを追加できるようにします。

テキストフィールドに何も入力されなかった場合には空の文字列が入るので``nil``になることはありません。
なので``textField.text!``としてあげて強制的アンラップします。

![ezgif.com-gif-to-mp4.gif](https://qiita-image-store.s3.amazonaws.com/0/259967/56af96cc-f97d-cf3b-9ea6-3ce7a86f5525.gif)





##**5. スワイプでのアイテム削除機能**
```swift:TodoListViewController
// MARK - スワイプでのアイテム削除機能
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        
        // アイテム削除処理
        itemArray.remove(at: indexPath.row)
        let indexPaths = [indexPath]
        tableView.deleteRows(at: indexPaths, with: .automatic)
        
    }
```
セルを左にスワイプすると**Delete**が出現するようになります。
タップするとアイテムを削除できます。
また、そのまま端までスワイプしても同じくアイテムを削除できます。

※アイテム追加時と同様に``tableview.reloadData()``でもok


![ezgif.com-optimize.gif](https://qiita-image-store.s3.amazonaws.com/0/259967/20870fd9-c064-96c1-a555-deb68a51d702.gif)


これでTodo Listアプリの完成です！！
お疲れ様でした！


#**おわりに**

UITableViewはどのアプリにも使われているので、しっかりとマスターしておきたいところです。
この記事にある程度の反応があれば、編集機能やダイナミックなUI、画面遷移やデータベースやアーキテクチャの内容を含んだ完全版のTodo Listアプリの作り方も書いてみようと思います！