- 某勉強会 で 教わった内容 の 復習用まとめ
- 講師
- 馬谷 さん
- TableView の実装を通じて
delegate
パターン を理解する - TableView の Cell の 表示 を delegate パターン(
UITableViewDataSource
) で 実装する- Cell の 表示 は
UITableViewCell
を利用する - → 次回:2018-09-01 の 勉強会では 自分で独自に定義した Cell クラス を利用
- Cell の 表示 は
- TableView の Cell が 選択された時の処理 を delegate パターン(
UITableViewDelegate
) で 実装する
- Class:
NewViewController
と 【入力】 - Subclass of:
UIViewController
と 【入力】 Also create XIB file
に チェック
import UIKit
// MARK: - Property
class NewViewController: UIViewController {
}
// MARK: - Life Cycle
extension NewViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
// MARK: - Protocol
extension NewViewController {
}
// MARK: - Method
extension NewViewController {
}
NewViewController.xib
を 【ファイル 選択】- 部品 を 配置
- TableView 【追加】
Outlet
を コード上に 【追加】- 変数名:
tableView
- 変数名:
- TableView 【追加】
NewViewController.swift
// MARK: - Property
class NewViewController: UIViewController {
+ @IBOutlet weak var tableView: UITableView!
}
// (以下略)
NewViewController.xib
を 【ファイル 選択】- TableView を 【選択】
- Constraints で 上/下/右/左 全て
0
に 【変更】
- Custom Class の
- Class:
NewViewController
に 【変更】
- Class:
Cmd + R
で 動作確認 (TableView が 表示される 事の確認)
- 参考画像
- 以下 の 2つ の いずれか の 方法
- TableView の 【
dataSource
を 指定】 - TableView を 表示する Controller (
NewViewController
) のviewDidLoad()
内で指定- 以下の コンパイルエラー が発生する
Cannot assign value of type 'NewViewController' to type 'UITableViewDataSource?' Insert ' as! UITableViewDataSource
NewViewController.swift
// MARK: - Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self // ★ 追加 (コンパイルエラー)
}
- 代入先/代入元 の 型が異なる ため
- 左辺: UITableView 型の
dataSource
はUITableViewDataSource?
Protocol 型 を要求 - 右辺:
self
(=NewViewController
型)UITableViewDataSource
Protocol は 未実装
- 左辺: UITableView 型の
コンパイルエラー を 解消するために
NewViewController
に 【UITableViewDataSource
Protocol を 実装】 させる: UITableViewDataSource
追加- 次は 以下の コンパイルエラー が発生する
Type 'NewViewController' does not conform to protocol 'UITableViewDataSource'
NewViewController.swift
// MARK: - Protocol
extension NewViewController: UITableViewDataSource { // ★ `: UITableViewDataSource` 追加 (コンパイルエラー)
}
UITableViewDataSource
Protocol で 定義されている 実装が必須 の メソッド をNewViewController
で 実装 していない ため- 実装が必須 = Protocol 内で
optional
が付いていない メソッド 全て UITableViewDataSource
の場合は 以下の2つtableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
- 実装が必須 = Protocol 内で
コンパイルエラー を 解消するために
- 上記 2つ の 【メソッド の 実装 を 追加】
- 戻り値 を 定義していないため まだ コンパイルエラー 発生
NewViewController.swift
// MARK: - Protocol
extension NewViewController: UITableViewDataSource {
// ★ メソッド追加
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// TODO 実装
}
// ★ メソッド追加
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// TODO 実装
}
}
tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
- 今回は 表示するデータ を 用意していないため, 【固定値(例:
100
) を返す】
- 今回は 表示するデータ を 用意していないため, 【固定値(例:
NewViewController.swift
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
- 標準で用意されている 【
UITableViewCell
を 生成 して 返す】UITableViewCell
内の 【textLabel
にindexPath.row
を 表示】
- 標準で用意されている 【
NewViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = String(indexPath.row)
return cell
}
import UIKit
// MARK: - Property
class NewViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
}
// MARK: - Life Cycle
extension NewViewController {
override func viewDidLoad() {
super.viewDidLoad()
+ tableView.dataSource = self
}
}
// MARK: - Protocol
-extension NewViewController {
+extension NewViewController: UITableViewDataSource {
+
+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ return 100
+ }
+
+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let cell = UITableViewCell()
+ cell.textLabel?.text = String(indexPath.row)
+ return cell
+ }
}
// MARK: - Method
extension NewViewController {
}
Cmd + R
で 動作確認 (TableView の 各 Cell に 0 から 始まる 数字 が 表示される 事の確認)
- TableView の 【
delegate
を 指定】 - TableView を 表示する Controller (
NewViewController
) のviewDidLoad()
内で指定- 以下の コンパイルエラー が発生する
Cannot assign value of type 'NewViewController' to type 'UITableViewDelegate?'
// MARK: - Life Cycle
extension NewViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self // ★ 追加 (コンパイルエラー)
}
}
- 代入先/代入元 の 型が異なる ため
- 左辺: UITableView 型の
delegate
はUITableViewDelegate?
Protocol 型 を要求 - 右辺:
self
(=NewViewController
型)UITableViewDelegate
Protocol は 未実装
- 左辺: UITableView 型の
コンパイルエラー を 解消するために
NewViewController
に 【UITableViewDelegate
Protocol を 実装】 させる: UITableViewDelegate
追加dataSource
の時とは違って, もう コンパイルエラー が発生しないUITableViewDelegate
は 全 メソッドoptional
が 付いている = 全て 実装は任意 のため
// MARK: - Protocol: UITableViewDataSource
extension NewViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
// 中略
}
// ★ 追加 ここから -------------------------------
// MARK: - Protocol: UITableViewDelegate
extension NewViewController: UITableViewDelegate {
}
// ★ 追加 ここまで -------------------------------
UITableViewDelegate
Protocol で 定義されている メソッドの中から- 画面の仕様を満たすために必要な 【メソッド の 実装 を 追加】
- 仕様:
- TableView 内の 任意の Cell が選択された 時に 画面遷移 する
- ->
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
を 実装
- ->
- どの Cell を選択しても, 全て同じ画面に遷移する 簡単な仕様 とする
- TableView 内の 任意の Cell が選択された 時に 画面遷移 する
// ★ メソッド追加
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
// TODO 実装
}
import UIKit
// MARK: - Property
class NewViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
}
// MARK: - Life Cycle
extension NewViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
+ tableView.delegate = self
}
}
-// MARK: - Protocol
+// MARK: - Protocol: UITableViewDataSource
extension NewViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = String(indexPath.row)
return cell
}
}
+// MARK: - Protocol: UITableViewDelegate
+extension NewViewController: UITableViewDelegate {
+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
+ let nextVC = TopViewController()
+ transitionVC(to: nextVC)
+ }
+}
// MARK: - Method
extension NewViewController {
+ func transitionVC(to: UIViewController) {
+ navigationController?.pushViewController(to, animated: true)
+ }
}
// MARK: - Protocol: UITableViewDelegate
extension NewViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let nextVC = TopViewController()
transitionVC(to: nextVC)
}
}
// MARK: - Method
extension NewViewController {
// ★ メソッド追加 (前回の勉強会 と同じ)
func transitionVC(to: UIViewController) {
navigationController?.pushViewController(to, animated: true)
}
}
Cmd + R
で 動作確認 (TableView の 各 Cell を 選択すると 画面遷移 する 事の確認)
- iOSアプリ開発勉強会 2018-09-01 に 続く...