【问题标题】:How to save UILabel from custom cell so that every time I open the app it displays the latest change?如何从自定义单元格中保存 UILabel,以便每次打开应用程序时都会显示最新更改?
【发布时间】:2019-06-27 12:35:13
【问题描述】:

我是 Swift 的初学者。我已经用尽了所有的尝试和错误,需要帮助!!

我正在使用带有自定义单元格的 UITableView 创建一个记分牌项目,该单元格包含一个 UILabel 和一个 UIButton。按下按钮后,UILabel 会增加 1 以模拟玩家的一个点。我无法在 UILabel 中保存积分,因此每次打开应用程序时,该玩家的积分都会保留。我尝试过使用 UserDefaults、结构和委托,但没有任何运气......我可能做错了。我只需要知道正确的方法是什么。

注意:我能够从 UIAlertController 成功保存玩家名称,这样当我打开应用程序时,名称仍然存在,除非我删除它们,但没有任何运气为每个名称本身保存点数,他们仍然是“0”。

当我关闭然后打开应用程序时应该看起来像这样,但它只在应用程序打开时才会这样做:

Scoreboard UITableView - Screenshot

ViewController 代码如下:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    var items = [String]()

    @IBOutlet weak var listTableView: UITableView!
    @IBAction func addItem(_ sender: AnyObject) {
        alert()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        listTableView.dataSource = self
        self.items = UserDefaults.standard.stringArray(forKey:"items")  ?? [String]()
    }

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

        cell.textLabel?.text = items[indexPath.row]

        return cell
    }


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

    func saveData() {
        UserDefaults.standard.set(items, forKey: "items")
    }

    func alert(){
        let alert = UIAlertController(title: "Add Player", message: "", preferredStyle: .alert)
        alert.addTextField{
            (textfield) in
            textfield.placeholder = " Enter Player Name "

        }
        let add = UIAlertAction(title: "Add", style: .default)
            {

            (action) in guard let textfield = alert.textFields?.first else {return}

            if let newText = textfield.text
            {
                self.items.append(newText)
                self.saveData()
                let indexPath = IndexPath(row: self.items.count - 1, section: 0)
                self.listTableView.insertRows(at: [indexPath], with: .automatic)
            }
        }

        let cancel = UIAlertAction(title: "Cancel", style: .cancel) {
            (alert) in

        }

        alert.addAction(add)
        alert.addAction(cancel)

        present(alert, animated: true, completion: nil)

    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        items.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .automatic)
        saveData()

    }

}

这是我的名为 PointsCell 的自定义单元格代码:

import UIKit

class PointsCell: UITableViewCell {

    var winScore = 0
    @IBOutlet weak var scoreUILabel: UILabel!

   @IBAction func pointButtonPressed(_ sender: Any) {
        winScore += 1
        scoreUILabel.text = "\(winScore)"

    }

}

【问题讨论】:

    标签: ios swift iphone uitableview nsuserdefaults


    【解决方案1】:

    积分仍然为 0,因为您注意保存它们,首先您需要每个玩家的积分,因此您需要将玩家姓名和得分结合到对象中。

    class Player:NSObject, Codable{
        let name: String
        var score : Int
        init(name: String, score: Int) {
            self.name = name
            self.score = score
        }
        override var description: String{
            return "Name :" + self.name + " Score :" + String(self.score )
        }
    }
    

    Swift 4 引入了 Codable 协议,通过在您自己的类型上采用 Codable,您可以将它们序列化为任何内置数据格式。

    现在您可以轻松访问具有姓名和得分的球员。

    var players = [Player]()
    

    UserDefaults获取存储值

    override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            if let items: Data = UserDefaults.standard.object(forKey: "items") as? Data{
                self.players = try! PropertyListDecoder().decode([Player].self, from: items)
                self.listTableView.reloadData()
            }
        }
    

    当您将新玩家添加到列表中时,创建 Player 的新实例并将其添加到列表中。

    func alert(){
        let alert = UIAlertController(title: "Add Player", message: "", preferredStyle: .alert)
        alert.addTextField{
            (textfield) in
            textfield.placeholder = " Enter Player Name "
    
        }
        let add = UIAlertAction(title: "Add", style: .default)
        {
            (action) in guard let textfield = alert.textFields?.first else {return}
            if let newText = textfield.text
            {
                let player = Player(name: newText, score: 0)
                self.players.append(player)
                let indexPath = IndexPath(row: self.players.count - 1, section: 0)
                self.listTableView.insertRows(at: [indexPath], with: .automatic)
            }
        }
    
        let cancel = UIAlertAction(title: "Cancel", style: .cancel) {
            (alert) in
    
        }
        alert.addAction(add)
        alert.addAction(cancel)
        present(alert, animated: true, completion: nil)
    
    }
    

    现在将您的 UITableViewDataSource 方法更新为新的列表项。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PointsCell
        cell.player = players[indexPath.row]
        return cell
    }
    

    现在需要更新saveData 方法以将新列表保存到UserDefaults,您可以在需要保存列表时调用此方法。

    func saveData() {
        UserDefaults.standard.set(try! PropertyListEncoder().encode(self.players), forKey: "items")
    }
    

    PointsCell 类也需要更新为新的对象类型:

    class PointsCell: UITableViewCell {
        @IBOutlet weak var scoreUILabel: UILabel!
        @IBOutlet weak var nameUILabel: UILabel!
    
        var player: Player? {
            didSet{
                if let name = player?.name {
                    self.nameUILabel?.text = name
                }
                if let score = player?.score {
                    self.scoreUILabel?.text = String(score)
                }
            }
        }
    
        @IBAction func pointbuttonPressed(_ sender: Any) {
            if self.player != nil{
                let score = self.player?.score ?? 0
                self.player?.score = score + 1
                scoreUILabel.text = String(self.player?.score ?? 0)
            }
        }
    }
    

    【讨论】:

    • 太棒了!谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多