質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Swift

    7658questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

tableViewCell 左端のチェックマークを維持したい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 322

tyobigorou

score 547

いつもお世話になります。

常時並び替え可能なテーブルビューにチェックマークを設定したところ、並び替え処理後に、チェックマークが維持できなくて困っています。
TableViewリロード時に、チェックマークが維持できなくて困っています。

UserDefaultなどをつかった、チェック済セルの永続化に必要なので、
tableView.allowsMultipleSelectionDuringEditing = true に設定した際にチェックマークの状態を示すセルのプロパティ名をご存知でしたら教えてください。

以前教えていただいたUILabelを使用して作ったものを、このチェックマークに置き換えたいと思うのですが、そもそも、このチェックマークの使い道自体が間違っているのでしょうか?

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var typesOfCatsArray: [String] = ["ジバニャン", "ワルニャン", "フユニャン", "イヌニャン", "サルニャン", "イチゴニャン"]
    // 選択済みの猫の種類を記憶する配列
    var selectedCatsArray: [String] = []

    @IBOutlet weak var typeOfCatsTableView: UITableView!


    //MARK: - LifeCycle -
    override func viewDidLoad() {
        super.viewDidLoad()

        // tableViewの編集を可能にする
        typeOfCatsTableView.isEditing = true
        //typeOfCatsTableView.allowsSelectionDuringEditing = true
        typeOfCatsTableView.allowsMultipleSelectionDuringEditing = true
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    //MARK: - UITableViewDataSource -

    // numberOfCell
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return typesOfCatsArray.count
    }

    // generateCell
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        let typeOfCatStr = typesOfCatsArray[indexPath.row]

        // typeOfCatsTableView.reloadData()時に、ここで選択済み配列に入っている猫の種類Cellにチェックマークを付けたいが記述方法がわからない。
        if selectedCatsArray.contains(typeOfCatStr) == true {
            //cell.isSelected = true
        } else {
            //cell.isSelected = false
        }

        cell.textLabel!.text = typeOfCatStr

        return cell
    }


    //MARK: - UITableViewDelegate -

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

        let selectedCatStr = typesOfCatsArray[indexPath.row]
        if selectedCatsArray.contains(selectedCatStr) == false {
            // 選択済み猫の種類を保存する
            selectedCatsArray.append(selectedCatStr)

            // 他のTableViewの配列に値を格納する

        }
    }

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

        let deselectedCatStr = typesOfCatsArray[indexPath.row]
        if let deleteCatIndex = selectedCatsArray.index(of: deselectedCatStr) {
            // 選択済み猫の種類を解除する
            selectedCatsArray.remove(at: deleteCatIndex)

            // 他のTableViewの配列から値を削除する
        }
    }

    // sortable
    func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    // editArray
    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let targetCatStr = typesOfCatsArray[sourceIndexPath.row]
        typesOfCatsArray.remove(at: sourceIndexPath.row)
        typesOfCatsArray.insert(targetCatStr, at: destinationIndexPath.row)

     // リロードを呼ばなければチェックマークが維持される。
     typeOfCatsTableView.reloadData()
    }

}

イメージ説明

↓UILabelを使用して作ったもの。

イメージ説明

//簡素化したコード。これ以外は、StoryboardにTableView・Cellを配置してCellのidentifierを設定、TableViewをOutlet接続しただけです。

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var typesOfCatsArray: [String] = ["ジバニャン", "ワルニャン", "フユニャン", "イヌニャン", "サルニャン", "イチゴニャン"]

    @IBOutlet weak var typeOfCatsTableView: UITableView!


    //MARK: - LifeCycle -
    override func viewDidLoad() {
        super.viewDidLoad()

        // tableViewの編集を可能にする
        typeOfCatsTableView.isEditing = true
        //typeOfCatsTableView.allowsSelectionDuringEditing = true
        typeOfCatsTableView.allowsMultipleSelectionDuringEditing = true
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    //MARK: - UITableViewDataSource -

    // numberOfCell
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return typesOfCatsArray.count
    }

    // generateCell
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel!.text = typesOfCatsArray[indexPath.row]

        return cell
    }

    // sortable
    func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    // editArray
    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let targetCatStr = typesOfCatsArray[sourceIndexPath.row]
        typesOfCatsArray.remove(at: sourceIndexPath.row)
        typesOfCatsArray.insert(targetCatStr, at: destinationIndexPath.row)
        typeOfCatsTableView.reloadData()
    }
}

解決方法備忘録

// generateCell
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = typeOfCatsTableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        let typeOfCatStr = typesOfCatsArray[indexPath.row]

        // typeOfCatsTableView.reloadData()時に、ここで選択済み配列に入っている猫の種類をselectする
        print("selectedCatsArray:",selectedCatsArray)
        if selectedCatsArray.contains(typeOfCatStr) == true {
           typeOfCatsTableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        } else {
            typeOfCatsTableView.deselectRow(at: indexPath, animated: false)
        }

        cell.textLabel!.text = typeOfCatStr

        return cell
    }

コード
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • tyobigorou

    2018/07/23 09:57 編集

    コード的には何も書いていないのです。cell.accessoryType = .checkmarkとか一切書いてないのです。なのでそもそもの使いみちが違うものなのかと…。チェックが付くだけのコードも載せたいと思います。

    キャンセル

  • fuzzball

    2018/07/23 10:10

    すみません、理解しました。チェックマークは自前で表示しているのではないんですね。こういうのがあることを知りませんでした。(ようするに、前回の回答は間違っていたということですね)

    キャンセル

  • tyobigorou

    2018/07/23 10:12

    いや、コードでチェックが制御できない以上、これは使いみちがちがうんじゃないかと思っているのですが、使えたらメンテがらくになるなと。cellがタップされたときに何が行われているか監視できたりすればわかるかなと思ってみたり。

    キャンセル

回答 1

checkベストアンサー

+1

//リロード前に選択済セルを取得
let indexPaths = tableView.indexPathsForSelectedRows
//リロード!
tableView.reloadData()
//選択済セルを復元
indexPaths?.forEach {
    tableView.selectRow(at: $0, animated: false, scrollPosition: .none)
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/23 10:42 編集

    cellForRowAt内のif文でところ.isSelectedを設定すると、プロパティをprintしたところtrueなのですが、画面上はすべてfalse(チェックなし)になってしまいます。
    「リロード後に…」というのは、cellForRowAtないでセルに設定してあげるという認識でよいでしょうか?

    キャンセル

  • 2018/07/23 10:48

    tableView(_:cellForRowAt:)内ではありません。
    .reloadData()の後です。

    キャンセル

  • 2018/07/23 11:02

    うーん、ダメですね。画面外のセルに反映させられないし、一旦画面から出ると未選択になっちゃいますね。

    キャンセル

  • 2018/07/23 11:03

    お時間取らせてしまって申し訳ないです。「reloadData()の後」とはどこでどうやって処理を行うのかイメージがわかないのですが、簡単でいいのでもうちょっと教えていただけないでしょうか?

    キャンセル

  • 2018/07/23 11:04

    https://qiita.com/ponkichi4/items/d5d46556773a6bc98f9c このへんでしょうか?

    キャンセル

  • 2018/07/23 11:07

    そんな難しい話ではなく、reloadData()の次の行です。(ダメだったのでアレですが‥)

    キャンセル

  • 2018/07/23 11:19

    別の方法を考えてみました。試してみて下さい。

    キャンセル

  • 2018/07/23 11:24

    なるほど、cellのプロパティではなく、tableViewのプロパティですね。
    試してみます。

    キャンセル

  • 2018/07/23 11:25 編集

    おみごとです。ありがとうございます。応用すればいろいろできそうです。

    キャンセル

  • 2018/07/23 11:32

    色々と失礼しました。
    私もいい勉強になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Swift

    7658questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています