如何保存tableview单元格的复选标记状态xcode 12 swift 5



我有一个类似于待办事项列表的简单应用程序。我使用TableViewController,我能够为每行设置复选标记附件类型,还找到了一种保存行数据的方法,以便当应用程序重新启动时再次显示项目列表。

我想保存所有行的复选标记状态。我在Stack Overflow中尝试了其他查询,其中大多数都过时了。

这是我的应用程序代码


class ViewController: UITableViewController {

var shoppingList = [ShoppingList]()

override func viewDidLoad() {
super.viewDidLoad()

title = "Shopping List"

navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addTapped))
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))

let clearList = UIBarButtonItem(title: "Clear List", style: .plain, target: self, action: #selector(clearList))

toolbarItems = [clearList]
navigationController?.isToolbarHidden = false

load()

tableView.tableFooterView = UIView() // clears the unused seperator lines

}

@objc func clearList() {

shoppingList.removeAll(keepingCapacity: true)
tableView.reloadData()
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
shoppingList.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)
cell.textLabel?.text = shoppingList[indexPath.row].itemName
cell.accessoryType = shoppingList[indexPath.row].checkmarkState ? .checkmark : .none
return cell
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
shoppingList.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCell.AccessoryType.checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.none
shoppingList[indexPath.row].checkmarkState = false
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.checkmark
shoppingList[indexPath.row].checkmarkState = true
}

save()
}

@objc func addTapped() {
let ac = UIAlertController(title: "New Shopping Item", message: nil, preferredStyle: .alert)
ac.addTextField()

let addAction = UIAlertAction(title: "Add", style: .default) {
[weak self, weak ac] _ in
guard let item = ac?.textFields?[0].text else { return }
self?.addItem(item)
}

ac.addAction(addAction)

ac.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

present(ac, animated: true)
}

@objc func shareTapped() {
}

func addItem(_ item: String) {
let itemCapitalised = item.capitalized
shoppingList.insert(ShoppingList(itemName: itemCapitalised), at: 0)

let indexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
save()
}

func showErrorMessage(errorTitle: String, errorMessage: String) {
let ac = UIAlertController(title: errorTitle, message: errorMessage, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Ok", style: .default))
present(ac, animated: true)
}

func save() {
let jsonEncoder = JSONEncoder()

if let savedData = try? jsonEncoder.encode(shoppingList) {
let defaults = UserDefaults.standard
defaults.set(savedData, forKey: "shoppingList")
} else {
print("Failed to save people.")
}
}

func load() {
let defaults = UserDefaults.standard

if let savedList = defaults.object(forKey: "shoppingList") as? Data {
let jsonDecoder = JSONDecoder()

do {
shoppingList = try jsonDecoder.decode([ShoppingList].self, from: savedList)
} catch {
print("Failed to load List")
}
}
}
}

由于您已经在模型中存储了checkmarkState,只需在tableView(_:cellForRowAt:)中添加cell.accessoryType = shoppingList[indexPath.row].checkmarkState ? .checkmark : .none以呈现复选标记状态。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)
cell.textLabel?.text = shoppingList[indexPath.row].itemName
cell.accessoryType = shoppingList[indexPath.row].checkmarkState ? .checkmark : .none
return cell
}

还有一种更好的方法来编写tableView(_:didSelectRowAt:):只需反转checkmarkState,然后重新加载行。

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

shoppingList[indexPath.row].checkmarkState = !shoppingList[indexPath.row].checkmarkState
tableView.reloadRows(at: [indexPath], with: .automatic)
save()
}

尽量记住MVC的理念。永远不要通过UI视图来确定模型的状态。仅由模型确定UI视图的状态。当您接收到用户输入时,直接更改模型,然后相应地重新呈现视图。保持模型作为真理的单一来源。

最新更新