tableView didSelectRowAt,didDeselectRowAtのIndexPathについて


はじめに

動きをわかっていない初心者の投稿です。
当たり前だろ!って内容ですのでお手柔らかにお願いします。

didSelectRowAtよりcheckをつけ、そのindexPath.rowを配列に格納

下の図のようなTableViewを作成する。

・つづいて記載したコード

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarDelegate{

    @IBOutlet weak var TableView: UITableView!   
    var checkflg = [Int]()

    //〜〜〜 省略 〜〜〜

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        print("▼▼▼▼▼▼▼▼ didSelectRowAt_process_bafore ▼▼▼▼▼▼▼▼")

        let cell = tableView.cellForRow(at: indexPath)
        cell?.accessoryType = .checkmark
        checkflg.append(indexPath.row)

        print("indexPath = \(indexPath)")
        print("indexPath.row = \(indexPath.row)" )
        print("checkflg重複処理前 = \(checkflg) ")

        let orderedSet = NSOrderedSet(array: checkflg)
        checkflg = orderedSet.array as! [Int]

        print("checkflg重複処理後 = \(checkflg) ")
        print("▲▲▲▲▲▲▲▲ didSelectRowAt_process_after ▲▲▲▲▲▲▲▲")

    }
}

タップしたもののindexPath.row (何行目?)をcheckflgという配列に格納していき、何がcheckをつけられたかの履歴を残す仕様。
1行目、3行目、2行目をタップ // checkflg = [0, 2, 1]
のようになる。

続いてlet orderedSet = NSOrderedSet(array: checkflg) にて重複した数字(1行目を2度タップなど)の除去
これがないと1行目、3行目、2行目、1行目をタップ // checkflg = [0, 2, 1, 0]
となってしまうため削除して再び checkflg に格納する。

実際に1行目、3行目、2行目、1行目をタップ

indexPath[section, rowIndex]
今回sectionで分けていないため全て0、rowIndexが変化していく。
indexPath.row にてきちんとタップした行の情報が表示されている。
また4つ目のデバッグから[0, 2, 1, 0]の配列が[0, 2, 1]となっており重複処理もできている。

あとはfunc てーぶるdidDeselectRowAtにてタップされた行番号を取得して
配列にその行番号があるか検索した後消せば、checkフラグを使用してチェックがうまいことつけられるのでは!?という状態。

didDeselectRowAt追加

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarDelegate{

    @IBOutlet weak var TableView: UITableView!   
    var checkflg = [Int]()

    //〜〜〜 省略 〜〜〜

     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        //print("▼▼▼▼▼▼▼▼ didSelectRowAt_process_bafore ▼▼▼▼▼▼▼▼")

        let cell = tableView.cellForRow(at: indexPath)
        cell?.accessoryType = .checkmark
        checkflg.append(indexPath.row)

        //print("indexPath = \(indexPath)")
        //print("indexPath.row = \(indexPath.row)" )
        //print("checkflg重複処理前 = \(checkflg) ")

        let orderedSet = NSOrderedSet(array: checkflg)
        checkflg = orderedSet.array as! [Int]

        //print("checkflg重複処理後 = \(checkflg) ")
        //print("▲▲▲▲▲▲▲▲ didSelectRowAt_process_after ▲▲▲▲▲▲▲▲")

     }

    //追加
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {

        print("▼▼▼▼▼▼▼▼ didDeselectRowAt_process_bafore ▼▼▼▼▼▼▼▼")
        print("checkflg検索&削除前 = \(checkflg) ")

        if let index = checkflg.index(of: indexPath.row){
            checkflg.remove(at: index)
        }

        print("checkflg検索&削除後 = \(checkflg) ")        
        print("▲▲▲▲▲▲▲▲ didDeselectRowAt_process_after ▲▲▲▲▲▲▲▲")

    }
}

if let index = checkflg.index(of: indexPath.row) にてindexPath.rowと同じ番号が配列に存在するかの検索を行う。もしあれば
checkflg.remove(at: index) にて削除する。

同じく1行目、3行目、2行目、1行目をタップ

計4回したのに3回しかログが流れていない。
しかも配列の中身が空になっている!!

・・・didSelectRowAtのログ復活&didDeselectRowAtにログ追加!

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {

        print("▼▼▼▼▼▼▼▼ didDeselectRowAt_process_bafore ▼▼▼▼▼▼▼▼")

        let cell = tableView.cellForRow(at: indexPath)
        cell?.accessoryType = .none

        print("indexPath = \(indexPath)")
        print("indexPath.row = \(indexPath.row)" )
        print("checkflg検索前 = \(checkflg) ")

        if let index = checkflg.index(of: indexPath.row){
            checkflg.remove(at: index)
        }

        print("checkflg検索後 = \(checkflg) ")
        print("▲▲▲▲▲▲▲▲ didDeselectRowAt_process_after ▲▲▲▲▲▲▲▲")

    }

再び1行目、3行目、2行目、1行目をタップ

非常に見にくいデバッグですいません。

ようするに
didSelectRowAtがはじめに呼ばれその後からタップするごとに
didDeselectRowAt→didSelectRowAtと呼ばれている。

つまり
didDeselectRowAtはタップされていたcellの情報を読み取り、また呼び出されるタイミングとしてはフォーカスが外れたタイミング。

結果

didSelectRowAt = 選択されたcellの情報
didDeselectRowAt = 選択されていたcellの情報

IndexPathは常に選択されていた行だと勘違いしていたがためのみす。

というか、、、英語読めば書いてあるじゃん。。

以上。
お付き合いありがとうございました。