19105


複数のセルを選択できるtableviewにおいて、ボタンを押した際に全セルが選択（チェックマークを入れる）されるようにしたいのですが方法がわかりません。ちなみに選択されたセルにチェックマークを入れる方法は下記で記述しています。

[code]

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let SelectCell = tableView.cellForRowAtIndexPath(indexPath)
        SelectCell?.accessoryType = .Checkmark
    }
    
[/code]

例えばbarbuttonitemで全セル選択のようなボタンを配置したいと考えています。  
よろしくお願いいたします。


CC BY-SA 3.0
2015-11-20T12:32:07.057
19092
2015-11-21T00:20:10.487
2015-11-20T12:41:52.447
7362
13350
question
ios swift tableview
tableViewの全セルを選択する方法


`UITableView`は、 **MVCデザインパターン**
に基づいて設計されています。MVCとは、「Model（データ）、View（表示）、Controller（仲介）」の略です。考え方は短時間で理解できるものではありませんが、`UITableView`に即したところだけ説明すると、データと表示を分けて考えようということです。  
問題です。行が100あるテーブルがあるとします。画面上表示されているのは10行です。ではこのテーブルはいくつのセルを持っているでしょうか？実験してみるとわかりますが、セルは100個ではありません。表示最大行10プラスアルファの数しかありません。テーブルをスクロールして、非表示になったセルは、姿を変えて、すぐに新しく表示になるセルとなります。テーブルは、場合によっては数万行におよぶ巨大なデータを扱うこともあります。そういうケースでもメモリ消費を抑えるために、こういう仕組みをとっています。それを支えているのが、データと表示を切り離すMVCの考え方です。  
前置きが長くなりましたが、セルにチェックマークを入れる外すというプログラムを考える前に、質問者さんのテーブルのプログラムを、最初から書き換えないといけないのではないか、ということがお分かりいただけますか？

サンプルプログラムを載せます。

[code]

    import UIKit
    
    class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
        @IBOutlet weak var tableView: UITableView!
        // テーブルに表示するデータを、配列で用意する。
        var dataArray: [[String: String]] = [[String: String]]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // データに、チェックマークをつけるかつけないかの項目を入れる。
            dataArray = [["name": "Apple", "check": "No"],
            ["name": "Banana", "check": "No"],
            ["name": "Candy", "check": "Yes"],
            ["name": "Donut", "check": "No"]]
        }
    
        // UITableViewDataSource
        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return dataArray.count
        }
    
        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
            cell.textLabel?.text = dataArray[indexPath.row]["name"]
            // チェックマークをつけるかつけないかを、ここで指示。
            cell.accessoryType = dataArray[indexPath.row]["check"] == "Yes" ? UITableViewCellAccessoryType.Checkmark : .None
    
            return cell
        }
    
        // セルをタップして選択する時の処理。チェックマーク表示をトグルで切り替える。
        // 「didSelectRow〜」じゃなくて「willSelectRow〜」なのに注意。
        func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
            // データを変更。
            let check = (dataArray[indexPath.row]["check"] == "Yes") ? "No" : "Yes"
        dataArray[indexPath.row]["check"] = check
        tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = (check == "Yes") ? .Checkmark : .None
            // セルの表示を変更。（注）
            tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = (check == "Yes") ? .Checkmark : .None
    
            return indexPath
        }
    
        // ボタンを押したら、全チェックにする。
        @IBAction func checkAll(sender: AnyObject) {
            // データを変更。
            for i in 0..<dataArray.count {
            dataArray[i]["check"] = "Yes"
        }
            // テーブルの再描画。
            tableView.reloadData()
        }
    
    }
    
[/code]

注：データを書き換えて、同時にセルのチェックマークの表示も切り替えるというのは、二度手間のように見えます。確かにそうで、ここは`tableView.reloadData()`でもいいのですが、表示のレスポンスが良くなるので、こうしています。

ポイントは、テーブルに表示するデータの構造を変更して、チェックマークの表示も情報として持つようにすること。テーブルにユーザ（人間）が変更を加えたら、それをデータに反映させるプログラムにするということです。


CC BY-SA 3.0
2015-11-21T00:09:43.097
19105
2015-11-21T00:20:10.487
2015-11-21T00:20:10.487
7362
7362
19092
answer