Loading
BLOG 開発者ブログ

2020年12月17日

【Swift】TableView内に配置したUISwitchのindexPath.rowを取得する


tableViewにUISwitchを追加する実装が必要になったのですが、
その際にタップされたUISwitchのindexPath.rowを取得するのに意外と苦労しました(汗)
調べてみると、同じような疑問にぶち当たっている方が多いようだったので、備忘録的に記事にしてみました。


この記事は アイソルート Advent Calendar 17日目の記事です。
こんにちは!3年目iOSエンジニアのide.tです。
iOSエンジニアの同志たちの助けになるような記事を書いていきたい所存です。

カスタムセルの作成

UISwitchはそのまま設置してタップイベントを取得するだけではタップされたセルがtableView内の何番目のセルなのか判別することができません。
そこで、cellのtagにindexPath.rowを保存することで自分がtableView内で何番目のcellなのか判別できるようにします。
上記を踏まえて以下のようなカスタムセルを作成しました。

class CustomSwitchCell: UITableViewCell {
    /// タイトルラベル
    @IBOutlet weak var titleLabel: UILabel!
    /// スイッチ
    @IBOutlet weak var mySwitch : UISwitch!
    /// コールバック
    var switchValueChangedCompletion: ((Bool, Int) -> Void)?
    
    // MARK: - IBAction Methods
    /// スイッチが変更された際に呼ばれる
    /// - Parameter sender: sender
    @IBAction func switchValueChanged(_ sender: Any) {
        // 変更後のスイッチ状態と自身のタグを返す
        switchValueChangedCompletion?(mySwitch.isOn, tag)
    }
}

カスタムセルの”switchValueChanged”メソッドはセル内のUISwitchがタップされた際に呼び出され、
プロパティに保持しているコールバックを実行します。

使用例

上記のカスタムセルを利用する際はViewControllerで以下のようにセルを作成する際にセルのタグにindexPath.rowを保存し、
スイッチを切り替えた際のコールバックにクロージャを渡します。
ここではViewController側で保持するスイッチの状態の更新とセルのラベルのメッセージの更新を行ってみました。

extension ViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return switchStatusArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomSwitchCell", for: indexPath) as! CustomSwitchCell
        // セルの初期化
        cell.mySwitch.isOn = switchStatusArray[indexPath.row]
        // セルのタグにindexPath.rowを持たせる
        cell.tag = indexPath.row
        // コールバックにスイッチ切り替え時の処理を登録
        cell.switchValueChangedCompletion = { [weak self] (switchStatus: Bool, indexRow: Int) in
            guard let self = self else { return }
            // DataSourceを更新
            self.switchStatusArray[indexRow] = switchStatus
            cell.titleLabel.text = switchStatus ? "ONです" : "OFFです"
            tableView.reloadData()
        }
        return cell
    }
}

実際に上記のTableViewを表示してみたものが以下になります。
タップされた3行目のセルのコールバックが実行され、ラベルの文字が「ONです」に変化しています。
しっかりとタップされたセルを判別して処理が実行できていますね!

最後に

TableViewに配置したUISwitchのindexPath.rowを取得する備忘録でした!
本記事がiOSエンジニア諸兄の役に立てば幸いです。
明日はimai.kさんのAzure Functionsで送信IPアドレスを固定したい話です。よろしくお願いします!


idetaのブログ