【Swift】【Xcode】TableViewの使い方。Part.2 コード編

#●まえがき
この記事はPart.1からの続きです。
まだみてない方は、Part.1へどうぞ！
[【Swift】【Xcode】詳しいTableViewの使い方。Part.1 準備編](https://qiita.com/akidon0000/items/850e6823363689912783)
#●解説
##目次
Part.1 
  1.プロジェクトの立ち上げ 
  2.Main.Storyboardの設定
  3.各種接続
 
Part.2 
  4.TableViewの設定
  5.多次元配列について
  6.残りのコードについて
  7.起動してみよう
  8.チャレンジ

##Step.4 TableViewの設定
###➀tableViewとクリアボタンを接続し,変数の宣言とメソッドの追加をします

```swift:ViewController.swift
import UIKit
//２次元配列　セルの内容が入る
var cellList:[[String]] = []
//セクションの名前が入る
var sectionTitles:[String] = []
//セクションの数
var sectionNum = 0
//セクションの高さ
var sectionHight:Int = 50
//セルの数
var cellNum:Int = 0
//セルの高さ
var cellHight:Int = 100
//セクション番号
var indexPath_section:Int = 0
//セル番号
var indexPath_row:Int = 0

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
    @IBOutlet weak var TableView: UITableView!
    @IBAction func Clear(_ sender: Any) {
    }
```

**ClassにUITableViewDelegate, UITableViewDataSourceを追加してください。**

###➁次にセクション内のセル数を決めるメソッドと、表示するcellの中身を決めるメソッドを追加します

```Swift:ViewController.swift
    /*
    セクション内のセル数を決めるメソッド（＊＊必須＊＊）
     */
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cellList[Int(section)].count
    }
    /*
    セルのインスタンスを生成するメソッド「表示するcellの中身を決める」（＊＊必須＊＊）
     */
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let TableCell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath)
        TableCell.textLabel!.text = cellList[indexPath.section][Int(indexPath.item)]
        return TableCell
    }
```

###➂セクション数を決めるメソッドとセクションの高さを決めるメソッド、セルの高さを決めるメソッドを追加

```Swift:ViewController.swift
    /*
     テーブル内のセクション数を決めるメソッド
     */
    func numberOfSections(in tableView: UITableView) -> Int {
        return sectionNum
    }
    
    /*
    セクションの高さを設定
    */
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return CGFloat(sectionHight)
    }
    
    /*
    セルの高さを決めるメソッド
     */
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return CGFloat(cellHight)
    }
```
###➃セクションのラベルを設定する

**セクションラベルはstoryboardで設定できないのでコードで記述します。**
**イメージとして、Viewの上にLabelとButtonを乗っける**
**func buttonTappedはセクションラベルに追加されたボタンをタップされるとこれが呼ばれます。**

```Swift:ViewController.swift
    /*
    セクションのラベルを設定する
     */
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UIView(frame: CGRect.zero) //zeroは目一杯に広げる
        //tableView.bounds.width はスマホの横幅を取得するメソッド
        let label = UILabel(frame: CGRect(x:0, y:0, width: tableView.bounds.width, height: 50))
        label.text = "\(sectionTitles[section])" //追加の際入力した文字を表示
        label.textAlignment = NSTextAlignment.center     //文字位置変更[.right][.center][.left]
        label.font = UIFont.italicSystemFont(ofSize: 21) //文字サイズ変更
        label.backgroundColor = UIColor.gray              //背景色変更
        label.textColor =  UIColor.black                 //文字色変更
        //self.view.frame.maxX は横幅の最大値を取得　基本的には左上が座標(0,0)
        let button = UIButton(frame: CGRect(x:self.view.frame.maxX - 50, y:0, width:50, height: 50))
        button.backgroundColor = UIColor.black
        button.setTitle("追加", for: .normal)
        button.tag = section //ボタンにタグをつける
        //追加ボタンがタップされた際に画面遷移をする(buttonTappedはタップされた際に呼び出される関数)
        button.addTarget(self, action: #selector(ViewController.buttonTapped(sender:)), for: .touchUpInside)
        //セクションバーの上にあるviewに加える 階層として sectionBar > view > label = button
        view.addSubview(label)
        view.addSubview(button)
        return view
    }
    @objc func buttonTapped(sender:UIButton){
        indexPath_section = sender.tag
        //同じstororyboard内であることをここで定義
        let storyboard: UIStoryboard = self.storyboard!
        //移動先のstoryboardを選択(Identifierを指定する)
        let second = storyboard.instantiateViewController(withIdentifier: "cellAdd")
        //実際に移動するコード
        self.present(second, animated: true, completion: nil)
    }
```

###⑤セルを選択した時のイベントを追加
```Swift:ViewController.swift
    /*
    セルを選択した時のイベントを追加
    */
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        indexPath_section = indexPath.section //記憶させてCellTapped.swiftで使う
        indexPath_row = indexPath.row
        //同じstororyboard内であることをここで定義
        let storyboard: UIStoryboard = self.storyboard!
        //移動先のstoryboardを選択(Identifierを指定する)
        let second = storyboard.instantiateViewController(withIdentifier: "cellTapped")
        //実際に移動するコード
        self.present(second, animated: true, completion: nil)
    }
    //元からあるコード
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
```
以上がViewController.swiftのコードです。

##Step.5 多次元配列について
多次元配列とは配列の中に配列が入ってるような物です。
詳しくは、この記事へどうぞ
[Swift 多次元配列の宣言、追加、削除について](https://qiita.com/akidon0000/items/80421c62ee16c59599ad)
**今回はセルの内容を記憶するためにこの多次元配列を使用します。**
わかりやすく例をあげると、下のような画像の時
**cellList = [["Tokyo"],["NewYork","Texas"],["Paris"]]**
となります。
![スクリーンショット 2020-01-07 14.42.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/5af2d508-f5d9-ac57-c99a-414f15d32401.png)


##Step.6 残りのコードについて
内容は簡単なのでさらっと紹介します。
ちなみに**func viewDidLoad()は画面が切り替わるたびに呼び出される関数**です。
###■SectionAdd.swift
```Swift:SectionAdd.swift
import UIKit

class SectionAdd: UIViewController {
    @IBOutlet weak var SectionTextField: UITextField!
    @IBAction func SectionAddButton(_ sender: Any) {
        //配列に入力内容を入れる
        sectionTitles.append(SectionTextField.text!)
        //追加ボタンを押したらフィールドを空にする
        SectionTextField.text = ""
        //セクションの数を１つ増やす。
        sectionNum += 1
        cellList.append([])
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
```

###■CellAdd.swift
```Swift:CellAdd.swift
import UIKit

class CellAdd: UIViewController {
    @IBOutlet weak var CellTextField: UITextField!
    @IBAction func CellAddButton(_ sender: Any) {
    //cellList.append([])
    cellList[indexPath_section].append(CellTextField.text!)
    //追加ボタンを押したらフィールドを空にする
    CellTextField.text = ""
    //セルの数を１つ増やす。
    cellNum += 1
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
```

###■CellTapped.swift
```Swift:CellAdd.swift
import UIKit

class CellTappedController: UIViewController {
    @IBOutlet weak var CellName: UILabel!
    @IBOutlet weak var CellNumber: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        CellName.text = cellList[indexPath_section][Int(indexPath_row)]
        CellNumber.text = "第\(indexPath_section)セクションの\(indexPath_row)個目のセル"
    }
}
```
##Step.7 起動してみよう
![スクリーンショット 2020-01-07 20.04.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/5a12663f-e5b7-cd8b-14c1-07e376c685c7.png)

うまく動かすことができましたね。お疲れ様でした！

##Step.8 チャレンジ！
やり足りないよという方はこちらを実装してみてください！！

・クリアの実装（＊ヒント＊.reloadData()を使うといいよ！）
・セクションバーについて
　　　　・xibを使ってカスタムセルを作る
　　　　・セルを再利用する
　　　　・画像を挿入してみる
　　　　・ボタンを追加してみる
　　　　・Disclosure Indicator　や　Checkmarkを実装してみる(＊ヒント＊storyboardからできるよ)
・アプリを閉じても内容が記憶されたままにしておく（＊UserDefaults＊を使用する）


#●あとがき
正月家にこもってずっとTableViewと格闘していました。この記事をみた方の役に立つことを願っています！