簡體   English   中英

如何保存tableview單元格xcode 12 swift 5的復選標記狀態

[英]How to save checkmark status of tableview cell 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 ,只需添加cell.accessoryType = shoppingList[indexPath.row].checkmarkState ? .checkmark : .none cell.accessoryType = shoppingList[indexPath.row].checkmarkState ? .checkmark : .nonetableView(_:cellForRowAt:)中呈現選中標記狀態。

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 視圖的狀態。 當您收到用戶輸入時,直接更改模型,然后相應地重新渲染視圖。 將模型作為唯一的事實來源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM