【问题标题】:Error when trying to save with user defaults尝试使用用户默认值保存时出错
【发布时间】:2020-04-05 08:41:39
【问题描述】:

我在将表视图数据保存为用户默认值时遇到问题,我在加载函数中收到错误“无法将类型 '[String]' 的值分配给类型 '[ViewController.ItemRow]'”。它在“items = loadedData”行给出错误。有谁知道它为什么给我这个错误!我不知道我是否做得对。

import UIKit
import SafariServices

class ViewController: UIViewController, UIAdaptivePresentationControllerDelegate, UITextFieldDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    @IBOutlet weak var OrderNumberLabel: RoundedLabel2!
    @IBOutlet weak var CostLabel: RoundedLabel2!
    @IBOutlet weak var ProfitLabel: RoundedLabel2!
    @IBOutlet weak var TotalLabel: RoundedLabel2!

    @IBOutlet weak var itemTextField: UITextField!
    @IBOutlet weak var priceTextField: UITextField!
    @IBOutlet weak var saleTextField: UITextField!

        var items: [ItemRow] = []

        struct ItemRow
        {
          var first: String
          var second: String
          var third: String
        }

        override func viewDidLoad() {
            super.viewDidLoad()
            load()
//            tableView.tableFooterView = UIView(frame: CGRect.zero)
        }


    func save(){
        UserDefaults.standard.set(items, forKey: "saved")

    }

    func load(){
        if let loadedData:[String] = UserDefaults.standard.value(forKey: "saved") as? [String]{
            items = loadedData
            tableView.reloadData()
        }

    }

    @IBAction func addButtonTapped(_ sender: Any) {
        insertNewItems()
        save()
//        profit()
//
    }

//    func profit(){
//        let priceValue = Double(priceTextField.text!)
//        let saleValue = Double(saleTextField.text!)
//
//        if priceValue != nil && saleValue != nil {
//
//            let outputValue = Double (priceValue! - saleValue!)
//
//            ProfitLabel.text = "\(outputValue)"
//            }
//    }


        func insertNewItems() {


            let newVideoRow = ItemRow(first: itemTextField.text!, second: priceTextField.text!, third: saleTextField.text!)
            items.append(newVideoRow)



            let indexPath = IndexPath(row: items.count - 1, section: 0)

            tableView.beginUpdates()
            tableView.insertRows(at: [indexPath], with: .automatic)
            tableView.endUpdates()


            itemTextField.text = ""
            priceTextField.text = ""
            saleTextField.text = ""

            view.endEditing(true)
        }

    }





    extension ViewController: UITableViewDelegate{

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


        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

             let ItemTitle = items[indexPath.row]

               let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell") as! ItemCell
               cell.itemLabel.text = ItemTitle.first
               cell.priceLabel.text = ItemTitle.second
               cell.saleLabel.text = ItemTitle.third
               return cell
        }


        func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
            return true
        }


        func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

            if editingStyle == .delete {
                items.remove(at: indexPath.row)

                tableView.beginUpdates()
                tableView.deleteRows(at: [indexPath], with: .automatic)
                tableView.endUpdates()
                save()
            }
        }
}

【问题讨论】:

  • 您将项目保存为struct,而不是string
  • items[ItemRow],而不是 [String]
  • 它必须是一个结构,所以我该如何修复
  • 可能你必须在loadedData中以[ItemRow]而不是[String]的形式获取数据

标签: ios swift


【解决方案1】:

使您的结构符合Codable 协议。这就像将一行更改为一样简单:-

struct ItemRow : Codable

您的save 函数可以是:-

if let data = try? PropertyListEncoder().encode(items) {
    UserDefaults.standard.set(data, forKey: "SavedItems")
}

load 可以是:

    let defaults = UserDefaults.standard
    if let data = defaults.data(forKey: "SavedItems") {
        items = try! PropertyListDecoder().decode([ItemRow].self, from: data)
        tableView.reloadData()
    }

快速浏览一下 SO,似乎认为这不应该用于大型数据集。所以这会让你开始,但如果你需要更多的数据(例如 CoreData 或 Realm),可能值得考虑一个更“数据库”的解决方案。

【讨论】:

  • 线程 1:致命错误:在加载函数中隐式展开“tableView.reloadData()”行上的可选值时意外发现 nil
  • 您是否将tableView 链接到视图控制器中的表格视图(因为您没有继承 UITableViewController)?检查插座是否连接到 Storyboard 中的表格视图。
  • 是的,它的链接
  • 如果您陈述的错误发生在您陈述的那一行,不,它不是。尝试使用 Ctrl-Drag 删除和重新链接。 tableViewtableView.reloadData 行上唯一的可选 var。
  • 我的意思是我只是取消链接并重新链接它,但仍然出现该错误
猜你喜欢
  • 2020-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
相关资源
最近更新 更多