Skip to content

Instantly share code, notes, and snippets.

@ohtsuchi
Last active September 7, 2018 12:21
Show Gist options
  • Save ohtsuchi/c2a1e3872ffea3440662877fd8df4fa7 to your computer and use it in GitHub Desktop.
Save ohtsuchi/c2a1e3872ffea3440662877fd8df4fa7 to your computer and use it in GitHub Desktop.
iOSアプリ開発勉強会 2018-09-01

iOSアプリ開発勉強会 2018-09-01

内容

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

目標

  • 自分で定義した TableViewCell クラス (SimpleTableViewCell) を TableView 上に 表示させる
  • 自分で定義した TableViewCell クラス (SimpleTableViewCell) 用の Delegate を 実装する
  • Controller 内に 配列 で準備した データ([UserModel]) を 各 Cell に 表示させる
  • TableView で 選択した Cell に 応じて 違う処理 を 振り分ける

1. 新規 TableViewCell クラス作成. SimpleTableViewCell.swift

  • Class: SimpleTableViewCell と 【入力】
  • Subclass of: UITableViewCell と 【入力】
  • Also create XIB file に チェック
  • 自動生成された 【メソッド を 全て削除】
    • awakeFromNib()
    • setSelected()
import UIKit
// MARK: -  Property
class SimpleTableViewCell: UITableViewCell {
}
// MARK: - Life Cycle
extension SimpleTableViewCell {
}
// MARK: - Protocol
extension SimpleTableViewCell {
}
// MARK: - Method
extension SimpleTableViewCell {
}
import UIKit
+// MARK: -  Property
class SimpleTableViewCell: UITableViewCell {
-
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        // Initialization code
-    }
-
-    override func setSelected(_ selected: Bool, animated: Bool) {
-        super.setSelected(selected, animated: animated)
-
-        // Configure the view for the selected state
-    }
-    
}
+// MARK: - Life Cycle
+extension SimpleTableViewCell {
+}
+// MARK: - Protocol
+extension SimpleTableViewCell {
+}
+// MARK: - Method
+extension SimpleTableViewCell {
+}

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

  • SimpleTableViewCell.xib を 【ファイル 選択】
  • 部品 を 配置
    • Label 【追加】
      • Outlet を コード上に 【追加】
        • 変数名: titleLabel
    • Button 【追加】
      • Action を コード上に 【追加】
        • メソッド名: touchButton
// MARK: -  Property
class SimpleTableViewCell: UITableViewCell {
+  @IBOutlet weak var titleLabel: UILabel!
+  @IBAction func touchButton(_ sender: UIButton) {
+  }
}
// (以下略)

 


3. TableView に 新規 TableViewCell を 登録(register)

  • tableView を配置している ViewController(NewViewController.swift) を 【ファイル選択】
  • viewDidLoad() 内で
    • 【 新規 TableViewCell を 登録(register) 】 する
      • nibName
        • = xib ファイルの名前 (="SimpleTableViewCell")
      • forCellReuseIdentifier =
        • = Cell 生成(or 使い回し)時(dequeueReusableCell()) の 引数 withIdentifier で 指定する ID 文字列
          • ここでは nibName と 同じ(="SimpleTableViewCell") にする
    let xib: UINib = UINib.init(nibName: "SimpleTableViewCell", bundle: nil)
    tableView.register(xib, forCellReuseIdentifier: "SimpleTableViewCell")

4. TableView の中の 【 各 Cell 】 を 生成(or 使い回し) して返す メソッド を 修正

  • 生成(or 使い回し) して返す クラス を 【変更】
    • UITableViewCell -> SimpleTableViewCell に 【変更】
  • UITableView
    • dequeueReusableCell() メソッド を利用
      • 100 行あったら 100 行分の View を作るわけではなくて
        • 表示される分だけの View を用意して、それを使い回す
      • withIdentifier
        • = register 時に forCellReuseIdentifier に 指定した ID 文字列 (="SimpleTableViewCell")
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell

 

NewViewController.swift

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

+    let xib: UINib = UINib.init(nibName: "SimpleTableViewCell", bundle: nil)
+    tableView.register(xib, forCellReuseIdentifier: "SimpleTableViewCell")
  }
}
// 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)
+    let cell: SimpleTableViewCell =
+      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
+        as! SimpleTableViewCell
    return cell
  }
}
// MARK: - Protocol: UITableViewDelegate
extension NewViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
    let nextVC = TopViewController()
    transitionViewController(to: nextVC)
  }
}
// MARK: - Method
extension NewViewController {
  func transitionViewController(to: UIViewController)  {
    navigationController?.pushViewController(to, animated: true)
  }
}

Cmd + R で 動作確認 (TableView の 各 Cell に Label と Button が 表示される 事の確認)

 

  let cellTypeName = String(describing: SimpleTableViewCell.self) // "SimpleTableViewCell"
    let xib: UINib = UINib.init(nibName: cellTypeName, bundle: nil)
    tableView.register(xib, forCellReuseIdentifier: cellTypeName)
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: cellTypeName, for: indexPath)
          as! SimpleTableViewCell

 


5. 新規 TableViewCell 用の Delegate を 新規作成

  • SimpleTableViewCell.swift 内に 【 新規 Protocol を 定義 】
    • NSObjectProtocol を 継承
  • UIButton を 引数 に 取る メソッド を 【実装】
    • touchButton(_ sender: UIButton)
      • @IBAction func touchButton(_ sender: UIButton) から 呼び出す メソッド
// ★ 新規追加 ここから -------------------------------
// MARK: - Delegate
protocol SimpleTableViewCellDelegate: NSObjectProtocol {
  func touchButton(_ sender: UIButton)
}
// ★ 新規追加 ここまで -------------------------------

// MARK: -  Property
class SimpleTableViewCell: UITableViewCell {
  @IBOutlet weak var titleLabel: UILabel!
  @IBAction func touchButton(_ sender: UIButton) {
  }
}
// 以下略

6. 新規 Delegate の 呼び出し を 実装

  • ↑で新規作成した Delegate を
    • SimpleTableViewCell の Property として 【実装】
  weak var delegate: SimpleTableViewCellDelegate? = nil
  • @IBAction func touchButton(_ sender: UIButton) 内に
    • Delegate を 呼び出す処理を 【実装】
  @IBAction func touchButton(_ sender: UIButton) {
    delegate?.touchButton(sender) // ★ 追加
  }

 

SimpleTableViewCell.swift

import UIKit
+// MARK: - Delegate
+protocol SimpleTableViewCellDelegate: NSObjectProtocol {
+  func touchButton(_ sender: UIButton)
+}

// MARK: - Property
class SimpleTableViewCell: UITableViewCell {
  @IBOutlet weak var titleLabel: UILabel!
  @IBAction func touchButton(_ sender: UIButton) {
+    delegate?.touchButton(sender)
  }
+  weak var delegate: SimpleTableViewCellDelegate? = nil
}
// MARK: - Life Cycle
extension SimpleTableViewCell {
}
// MARK: - Protocol
extension SimpleTableViewCell {
}
// MARK: - Method
extension SimpleTableViewCell {
}

Cmd + R で 動作確認 (動作結果 は 前と変わらず. エラーが発生しない事の確認)

 


7. Delegate 先 (NewViewController) の 実装

  • NewViewController.swift を 【ファイル選択】
  • 元々の Delegate (=UITableViewDelegate) の 実装 を 全て 【削除】
-// MARK: - Protocol: UITableViewDelegate
-extension NewViewController: UITableViewDelegate {
-  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
-    let nextVC = TopViewController()
-    transitionVC(to: nextVC)
-  }
-}
  • viewDidLoad() 内の
    • tableView.delegate = self が コンパイルエラー になるので 【削除】
    • ↑ で NewViewController から UITableViewDelegate の 実装 を 消したため
      • 代入先/代入元 の 型が異なる
        • 左辺: UITableView 型の delegateUITableViewDelegate? Protocol 型 を要求
        • 右辺: self(= NewViewController 型)
          • UITableViewDelegate Protocol は 未実装
-    tableView.delegate = self
  • 新規 Delegate (=SimpleTableViewCellDelegate) を 【実装】
// ★ 新規追加
// MARK: - Protocol: SimpleTableViewCellDelegate
extension NewViewController: SimpleTableViewCellDelegate {
  func touchButton(_ sender: UIButton) {
    let nextVC = TopViewController()
    transitionVC(to: nextVC)
  }
}
  • Cell(SimpleTableViewCell) 生成(or 使い回し)時 に delegate を指定する処理を 【実装】
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell
    cell.delegate = self // ★ 追加
    return cell
  }

 

NewViewController.swift

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

    let xib: UINib = UINib.init(nibName: "SimpleTableViewCell", bundle: nil)
    tableView.register(xib, forCellReuseIdentifier: "SimpleTableViewCell")
  }
}
// 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: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell
+    cell.delegate = self
    return cell
  }
}
-// MARK: - Protocol: UITableViewDelegate
-extension NewViewController: UITableViewDelegate {
-  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
-    let nextVC = TopViewController()
-    transitionVC(to: nextVC)
-  }
-}
+// MARK: - Protocol: SimpleTableViewCellDelegate
+extension NewViewController: SimpleTableViewCellDelegate {
+  func touchButton(_ sender: UIButton) {
+    let nextVC = TopViewController()
+    transitionVC(to: nextVC)
+  }
+}

// MARK: - Method
extension NewViewController {
  func transitionVC(to: UIViewController)  {
    navigationController?.pushViewController(to, animated: true)
  }
}

Cmd + R で 動作確認 (TableView の 各 Cell の Button を選択すると 画面遷移 される 事の確認)

 


8. データ(UserModel 一覧) を TableView の Cell (SimpleTableViewCell) に 表示

  • NewViewController 内で
    • UserModel の 配列 を Property で 保持して
      • UserModel の 情報を SimpleTableViewCell に 表示 させる

SimpleTableViewCell に 表示メソッド を 実装

  • 自分自身 を 変更する メソッド を 【実装】
    • Cell の 生成(or 使い回し)時delegate 先 から 呼び出される
  func updateCell(userModel: UserModel) {
    titleLabel.text = userModel.name
  }

SimpleTableViewCell.swift

import UIKit

// MARK: - Delegate
protocol SimpleTableViewCellDelegate: NSObjectProtocol {
  func touchButton(_ sender: UIButton)
}

// MARK: - Property
class SimpleTableViewCell: UITableViewCell {
  @IBOutlet weak var titleLabel: UILabel!
  @IBAction func touchButton(_ sender: UIButton) {
    delegate?.touchButton(sender)
  }

  weak var delegate: SimpleTableViewCellDelegate? = nil
}
// MARK: - Life Cycle
extension SimpleTableViewCell {
}
// MARK: - Protocol
extension SimpleTableViewCell {
}
// MARK: - Method
extension SimpleTableViewCell {
+  func updateCell(userModel: UserModel) {
+    titleLabel.text = userModel.name
+  }
}

NewViewController に データ用意

  • UserModel の 配列 を Property として 【実装】
  var userModels: [UserModel] = []
  • UserModel の 配列 を 初期化 する メソッド を 【実装】
    • ダミーデータとして 3件 用意
  func createUserModel(name: String, age: Int?) -> UserModel {
    let u = UserModel()
    u.name = name
    u.age = age
    return u
  }
  func setUserModels() {
    let u1 = createUserModel(name: "user1", age: 20)
    let u2 = createUserModel(name: "user2", age: nil)
    let u3 = createUserModel(name: "user3", age: 60)
    userModels += [u1]
    userModels += [u2]
    userModels += [u3]
  }
  • Cell の 行数 を 返す メソッド で
    • UserModel の 配列 の 件数 を 返す 処理に 【変更】
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return userModels.count // ★ 修正
  }
  • 各 Cell(SimpleTableViewCell) を 生成(or 使い回し) する メソッド で
    • UserModel の 情報を Cell (SimpleTableViewCell) に 渡す 処理を 【実装】
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell
    cell.delegate = self
    // ★ 追加 ここから -----------------------
    let userModel = userModels[indexPath.row]
    cell.updateCell(userModel: userModel)
    // ★ 追加 ここまで -----------------------
    return cell
  }
  • viewDidLoad()
    • UserModel の 配列 の 初期化 を 【呼び出し】
    • UITableViewreloadData() も 【呼び出し】
      • TableView 全体を更新
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self

    let xib: UINib = UINib.init(nibName: "SimpleTableViewCell", bundle: nil)
    tableView.register(xib, forCellReuseIdentifier: "SimpleTableViewCell")

    // ★ 追加 ここから -----------------------
    setUserModels()
    tableView.reloadData()
    // ★ 追加 ここまで -----------------------
  }

 

NewViewController.swift

import UIKit
// MARK: - Property
class NewViewController: UIViewController {
  @IBOutlet weak var tableView: UITableView!
+  var userModels: [UserModel] = []
}
// MARK: - Life Cycle
extension NewViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self

    let xib: UINib = UINib.init(nibName: "SimpleTableViewCell", bundle: nil)
    tableView.register(xib, forCellReuseIdentifier: "SimpleTableViewCell")

+    setUserModels()
+    tableView.reloadData()
  }
}
// MARK: - Protocol: UITableViewDataSource
extension NewViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-    return 100
+    return userModels.count
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell
    cell.delegate = self
+    let userModel = userModels[indexPath.row]
+    cell.updateCell(userModel: userModel)
    return cell
  }
}
// MARK: - Protocol: SimpleTableViewCellDelegate
extension NewViewController: SimpleTableViewCellDelegate {
  func touchButton(_ sender: UIButton) {
    let nextVC = TopViewController()
    transitionVC(to: nextVC)
  }
}

// MARK: - Method
extension NewViewController {
  func transitionVC(to: UIViewController)  {
    navigationController?.pushViewController(to, animated: true)
  }
+  func createUserModel(name: String, age: Int?) -> UserModel {
+    let u = UserModel()
+    u.name = name
+    u.age = age
+    return u
+  }
+  func setUserModels() {
+    let u1 = createUserModel(name: "user1", age: 20)
+    let u2 = createUserModel(name: "user2", age: nil)
+    let u3 = createUserModel(name: "user3", age: 60)
+    userModels += [u1]
+    userModels += [u2]
+    userModels += [u3]
+  }
}

Cmd + R で 動作確認 (TableView の Cell の 行数が 3行, 各 Cell の Label に UserModel.name の 中身 が 表示 される 事の確認)

 


9. データ(UserModel) の id で 処理を振り分け

  • 仕様
    • id には indexPath.row の 値 を入れる
    • 3件のデータのうち
      • 1件目 は TopViewController に 遷移
      • 2件目 は SecondViewController に 遷移
      • 3件目 は 何もしない

UserModel に Property(id) 追加

  • Objective C では id は 予約語 のため 使用できない らしい
    • Objective C と swift の 混合 Project だと コンパイルエラー になる ??

UserModel.swift

import UIKit

class UserModel: NSObject {
+  var id: Int?
  var name: String?
  var age: Int?
}

SimpleTableViewCellUserModel を 保持

  • UserModel を Property として 【実装】
  var userModel: UserModel = UserModel()
  • Cell の 生成(or 使い回し)時delegate 先 から 呼び出される メソッド 内で
    • UserModel を Property に セット
  func updateCell(userModel: UserModel) {
    self.userModel = userModel  // ★ 追加
    titleLabel.text = userModel.name
  }

Protocol(SimpleTableViewCellDelegate) の メソッド 定義 を 変更

  • ボタン の 選択時Delegate 先 に UserModel を 返す ように 【 Protocol を 改修 】
protocol SimpleTableViewCellDelegate: NSObjectProtocol {
  func touchButton(_ sender: UIButton, userModel: UserModel) // ★ 第2引数 追加
}
  @IBAction func touchButton(_ sender: UIButton) {
    delegate?.touchButton(sender, userModel: userModel) // ★ 第2引数 追加
  }

 

SimpleTableViewCell.swift

import UIKit

// MARK: - Delegate
protocol SimpleTableViewCellDelegate: NSObjectProtocol {
-  func touchButton(_ sender: UIButton)
+  func touchButton(_ sender: UIButton, userModel: UserModel)
}

// MARK: - Property
class SimpleTableViewCell: UITableViewCell {
  @IBOutlet weak var titleLabel: UILabel!
  @IBAction func touchButton(_ sender: UIButton) {
-    delegate?.touchButton(sender)
+    delegate?.touchButton(sender, userModel: userModel)
  }

  weak var delegate: SimpleTableViewCellDelegate? = nil
+  var userModel: UserModel = UserModel()
}
// MARK: - Life Cycle
extension SimpleTableViewCell {
}
// MARK: - Protocol
extension SimpleTableViewCell {
}
// MARK: - Method
extension SimpleTableViewCell {
  func updateCell(userModel: UserModel) {
+    self.userModel = userModel
    titleLabel.text = userModel.name
  }
}
  • この時点で NewViewController.swift に 以下の コンパイルエラー 発生
    • Type 'NewViewController' does not conform to protocol 'SimpleTableViewCellDelegate'

Delegate 先 (NewViewController) を Protocol (SimpleTableViewCellDelegate) に 適合 させる

  • 【引数を追加】
  func touchButton(_ sender: UIButton, userModel: UserModel) { // ★ 第2引数 追加
    let nextVC = TopViewController()
    transitionVC(to: nextVC)
  }

データ(UserModel) の id で 処理を振り分け

  • ↑ の メソッド の 内容 を 【変更】
  func touchButton(_ sender: UIButton, userModel: UserModel) {
    // 変数:nextVC は UIViewController 型
    var nextVC = UIViewController()

    switch userModel.id {
    case 0:
      nextVC = TopViewController()
    case 1:
      // 変数:nextVC は UIViewController 型
      //   (実体は SecondViewController 型の instance)
      nextVC = SecondViewController()

      // ダウンキャスト する方法(1) if let as? 使用
      if let vc = nextVC as? SecondViewController {
        // 変数:vc は SecondViewController 型
        vc.userModel.name = "userX"
      }

      // ダウンキャスト する方法(2) 別の変数 使用  
      //   ( ViewController は class で参照型のため
      //     `nextVC` と `vc2` は同じ instance を指し示す)
      let vc2 = nextVC as! SecondViewController
      vc2.userModel.age = 99

    default:
      return
    }
    transitionVC(to: nextVC)
  }

Cell (SimpleTableViewCell) の 生成(or 使い回し)時 に UserModelid を セット

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell
    cell.delegate = self
    let userModel = userModels[indexPath.row]
    userModel.id = indexPath.row // ★ 追加
    cell.updateCell(userModel: userModel)
    return cell
  }

 

NewViewController.swift

import UIKit
// MARK: - Property
class NewViewController: UIViewController {
  @IBOutlet weak var tableView: UITableView!
  var userModels: [UserModel] = []
}
// MARK: - Life Cycle
extension NewViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self

    let xib: UINib = UINib.init(nibName: "SimpleTableViewCell", bundle: nil)
    tableView.register(xib, forCellReuseIdentifier: "SimpleTableViewCell")

    setUsers()
    tableView.reloadData()
  }
}
// MARK: - Protocol: UITableViewDataSource
extension NewViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return userModels.count
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: SimpleTableViewCell =
      tableView.dequeueReusableCell(withIdentifier: "SimpleTableViewCell", for: indexPath)
        as! SimpleTableViewCell
    cell.delegate = self
    let userModel = userModels[indexPath.row]
+    userModel.id = indexPath.row
    cell.updateCell(userModel: userModel)
    return cell
  }
}
// MARK: - Protocol: SimpleTableViewCellDelegate
extension NewViewController: SimpleTableViewCellDelegate {
-  func touchButton(_ sender: UIButton) {
+  func touchButton(_ sender: UIButton, userModel: UserModel) {
-    let nextVC = TopViewController()
+    var nextVC = UIViewController()
+
+    switch userModel.id {
+    case 0:
+      nextVC = TopViewController()
+    case 1:
+      nextVC = SecondViewController()
+
+      if let vc = nextVC as? SecondViewController {
+        vc.userModel.name = "userX"
+      }
+
+      let vc2 = nextVC as! SecondViewController
+      vc2.userModel.age = 99
+
+    default:
+      return
+    }
    transitionVC(to: nextVC)
  }
}

// MARK: - Method
extension NewViewController {
  func transitionVC(to: UIViewController)  {
    navigationController?.pushViewController(to, animated: true)
  }
  func createUser(name: String, age: Int?) -> UserModel {
    let u = UserModel()
    u.name = name
    u.age = age
    return u
  }
  func setUsers() {
    let u1 = createUser(name: "user1", age: 20)
    let u2 = createUser(name: "user2", age: nil)
    let u3 = createUser(name: "user3", age: 60)
    userModels += [u1]
    userModels += [u2]
    userModels += [u3]
  }
}

Cmd + R で 動作確認 (TableView の 1行目, 2行目 の Cell の Button を 選択すると 別々の画面に 遷移 される, 3行目 は 何も起きない 事の確認)

 


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