在 swift 4.2 的 table 视图中保存勾选单元格的状态

Save the state of checkmarked cell in table view in swift 4.2

我在视图控制器中制作了一个 table 视图并以编程方式填充它。我可以根据需要一次在单元格上打勾,但是当我回到那个屏幕时,它不在那里。

这些是我的数组:

let devCourses = [("Sound"),("Vibrate"),("Both"),("None")]

let devCousesImages = [UIImage(named: "speaker"), UIImage(named: "Group 1094"), UIImage(named: "Group 1093"), UIImage(named: "speaker-1")]

这是我的 didSelectRowAt 代码:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark

    }

这是 didDeselectRowAt 的代码:

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        tableView.cellForRow(at: indexPath)?.accessoryType = .none
    }



func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell=tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as! VibTableViewCell

        let courseTitle = devCourses[indexPath .row]

        let Images = devCousesImages[indexPath .row]

        cell.label.text=courseTitle
        cell.label.textColor = UIColor.darkGray
        cell.photo.image=Images

        return cell
    }

我希望当我回到屏幕时复选标记在那里

因为您想返回查看控制器以显示所选单元格。然后你要维护选定的单元格数组,然后在 viewDidLoad/viewWillappear 中将选定的单元格设置为下面的代码

for index in selectedArray {
            self.tableView.selectRow(at: IndexPath(row: index, section: 0), animated: false, scrollPosition: .none)
        }

创建一个字典[IndexPath:Bool] 以跟踪选择了哪些行的状态。

var dict: [IndexPath:Bool] = [:]

tableView(_:, didSelectRowAt:) 中添加以下行:

dict[indexPath] = true

tableView(_:, didDeselectRowAt:) 中添加以下行:

dict[indexPath] = false

tableView(_:, cellForRowAt:)中添加以下行:

let selected = dict[indexPath] ?? false
cell.accessoryType = selected ? .checkmark : .none

首先使用一个结构作为数据源而不是多个数组。

也不要使用额外的数组或字典来维护选择,这很容易出错并且不必要地昂贵。

将布尔成员添加到所选状态的结构。

struct Course : Codable {
    let name : String
    let image : String
    var isSelected : Bool
}

声明数据源数组

var courses = [Course(name: "Sound", image: "speaker", isSelected: false),
               Course(name: "Vibrate", image: "Group 1094", isSelected: false),
               Course(name: "Both", image: "Group 1093", isSelected: false),
               Course(name: "None", image: "speaker-1", isSelected: false)]

cellForRowAt中根据isSelected设置复选标记

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! VibTableViewCell
    let course = courses[indexPath.row]
    cell.label.text = course.name
    // define the text color in Interface Builder
    // cell.label.textColor = UIColor.darkGray
    cell.photo.image = UIImage(named: course.image)
    cell.accessoryType = course.isSelected ? .checkmark : .none

    return cell
}

didSelectRowAt 中切换数据源中的 isSelected 值并重新加载行

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    courses[indexPath.row].isSelected.toggle()
    tableView.reloadRows(at: indexPath, with: .none)
}

最后删除方法didDeselectRowAt

要保存你可以写的数组

do {
    let data = try JSONEncoder().encode(courses)
    UserDefaults.standard.set(data, forKey: "Courses")
} catch { print(error) }

你可以使用我的解决方案。

使用 NSCoder 在 plist 文件中保存单元格状态。即使您重新启动应用程序 - 您也不会丢失数据。

import UIKit

class TableViewController: UITableViewController {

    var itemsArray : [Item] = [Item(name: "mom", done: true), Item(name: "pap", done: false), Item(name: "Lena", done: false), Item(name: "Gleb", done: false), Item(name: "Sasha", done: false), Item(name: "Max", done: false)]


    /* path to custom plist file */
    let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("Items.plist")

    override func viewDidLoad() {
        super.viewDidLoad()

        if let filePath = dataFilePath {
            print(filePath)
        }

        loadData()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return itemsArray.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        let item = itemsArray[indexPath.row]
        cell.accessoryType = item.done ? .checkmark : .none
        cell.textLabel?.text = item.name
        // Configure the cell...

        return cell
    }

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

        itemsArray[indexPath.row].done = !itemsArray[indexPath.row].done

        /* when state is changed - save it to plist file */
        saveDate()

        tableView.deselectRow(at: indexPath, animated: true)
    }


    /* save array to plist file (you can see it inside folder from consol) */
    func saveDate() {
        let encoder = PropertyListEncoder()
        do {
            let data = try encoder.encode(itemsArray)
            try data.write(to: dataFilePath!)
        } catch {
            print(error.localizedDescription)
        }
        self.tableView.reloadData()
    }


    /* load data from plist file */
    func loadData() {

        if let data = try? Data(contentsOf: dataFilePath!) {
            let decoder = PropertyListDecoder()
            do {
                itemsArray = try decoder.decode([Item].self, from: data)
            } catch {
                print(error.localizedDescription)
            }
        }

    }
}

数据模型:

import Foundation

struct Item : Encodable, Decodable {
    var name : String = ""
    var done : Bool = false
}