Skip to content

Instantly share code, notes, and snippets.

@ohtsuchi
Last active September 9, 2018 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ohtsuchi/30a36298f9532ecebd6e0903cf83bcb8 to your computer and use it in GitHub Desktop.
Save ohtsuchi/30a36298f9532ecebd6e0903cf83bcb8 to your computer and use it in GitHub Desktop.
iOSアプリ開発勉強会 2018-08-25

iOSアプリ開発勉強会 2018-08-25

内容

  • 某勉強会 で 教わった内容 の 復習用まとめ
  • 講師
    • 馬谷 さん

目標

  • TableView の実装を通じて delegate パターン を理解する
  • TableView の Cell の 表示 を delegate パターン(UITableViewDataSource) で 実装する
    • Cell の 表示 は UITableViewCell を利用する
    • 次回:2018-09-01 の 勉強会では 自分で独自に定義した Cell クラス を利用
  • TableView の Cell が 選択された時の処理 を delegate パターン(UITableViewDelegate) で 実装する

1. 新規 UIViewController 作成. NewViewController.swift

  • 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 {
}

2. 画面レイアウト(NewViewController.xib), コード(NewViewController.swift) 実装

  • NewViewController.xib を 【ファイル 選択】
  • 部品 を 配置
    • TableView 【追加】
      • Outlet を コード上に 【追加】
        • 変数名: tableView

NewViewController.swift

// MARK: - Property
class NewViewController: UIViewController {
+  @IBOutlet weak var tableView: UITableView!
}
// (以下略)

3. TableView の Constraints(AutoLayout) を 定義.

  • NewViewController.xib を 【ファイル 選択】
  • TableView を 【選択】
  • Constraints で 上/下/右/左 全て 0 に 【変更】

4. Main.storyboard から 起動される UIViewController を 変更

  • Custom Class の
    • Class: NewViewController に 【変更】

Cmd + R で 動作確認 (TableView が 表示される 事の確認)

 


5. delegate パターン ( TableView の datasource, delegate ) について 概要を把握

delegate 先 ( TableView の datasource, delegate ) の 指定方法

 


6. TableView の dataSource 指定

  • 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 型の dataSourceUITableViewDataSource? Protocol 型 を要求
    • 右辺: self(= NewViewController 型)
      • UITableViewDataSource Protocol は 未実装

  コンパイルエラー を 解消するために

  • NewViewControllerUITableViewDataSource 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

  コンパイルエラー を 解消するために

  • 上記 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 に表示する Cell の 【 行数 】 を返す メソッド を 実装

  • tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    • 今回は 表示するデータ を 用意していないため, 【固定値(例: 100) を返す】

NewViewController.swift

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 100
  }

TableView の中の 【 各 Cell 】 を 生成して返す メソッド を 実装

  • tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    • 標準で用意されている 【UITableViewCell を 生成 して 返す】
      • UITableViewCell 内の 【textLabelindexPath.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 から 始まる 数字 が 表示される 事の確認)

 


7. TableView の delegate 指定

  • 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 型の delegateUITableViewDelegate? Protocol 型 を要求
    • 右辺: self(= NewViewController 型)
      • UITableViewDelegate Protocol は 未実装

  コンパイルエラー を 解消するために

  • NewViewControllerUITableViewDelegate 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 {
}
// ★ 追加 ここまで -------------------------------

TableView の中の 【 各 Cell が選択された時 】 に呼び出される メソッド を 実装

  • UITableViewDelegate Protocol で 定義されている メソッドの中から
    • 画面の仕様を満たすために必要な 【メソッド の 実装 を 追加】
  • 仕様:
    • TableView 内の 任意の Cell が選択された 時に 画面遷移 する
      • -> tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) を 実装
    • どの 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 を 選択すると 画面遷移 する 事の確認)

 


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment