swift中如何使用Userdefaults存储UItableview数据?

How to use Userdefaults to store UItableview data in swift?

现在我将商品添加到购物车时显示正确。但是当我重新打开页面时,数据丢失了。我正在尝试将 cartTableView 数据存储在 userdefaults 中。我尝试了几种方法,但无法出现。 这是我的 cartViewController 代码:

import UIKit
class CartViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    var arrdata = [jsonstruct]()
    var categorydata = [Categories]()
    var imgdata = [Images]()
    
    var cartArray = [CartStruct]()
    
    @IBOutlet var cartTableView: UITableView!
    
    @IBOutlet var totalCount: UILabel!
    @IBOutlet var subtotalPrice: UILabel!
    @IBOutlet var shippingPrice: UILabel!
    @IBOutlet var totalPrice: UILabel!
    @IBOutlet var proceedBtn: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        cartArray = (UserDefaults.standard.array(forKey: "cartt") as? [CartStruct])!
        cartTableView.reloadData()

    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cartArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "CartCellTableViewCell", for: indexPath) as! CartCellTableViewCell
 
        cell.cartImageView.downloadImage(from: cartArray[indexPath.row].cartItems.images.first?.src ?? "place_holder_image")

        cell.productNameCart.text = cartArray[indexPath.row].cartItems.name
        cell.prodductDescCart.text = cartArray[indexPath.row].cartItems.categories.first?.type
        cell.productPriceCart.text = cartArray[indexPath.row].cartItems.price
        
        cell.addBtn.addTarget(self, action: #selector(add(sender:)), for: .touchUpInside)
        cell.addBtn.tag = indexPath.row
        
        let cartQuantity = cartArray[indexPath.row].cartQuantity
        cell.prodCount.text = "\(cartQuantity)"
        
        if cartQuantity >= 0 {
            cell.subBtn.isUserInteractionEnabled = true;
            cell.subBtn.addTarget(self, action: #selector(sub(sender:)), for: .touchUpInside)
            cell.subBtn.tag = indexPath.row
        } else {
            cell.subBtn.isUserInteractionEnabled = false;
        }
        return cell
    }
    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            cartArray.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
            tableView.reloadData()
        }
    }
    
    @objc func add(sender: UIButton){
        if cartArray[sender.tag].cartQuantity >= 0 {
            cartArray[sender.tag].cartQuantity += 1
            cartTableView.reloadData()
        }
    }
    
    @objc func sub(sender: UIButton){
        if cartArray[sender.tag].cartQuantity > 0 {
            cartArray[sender.tag].cartQuantity -= 1
            cartTableView.reloadData()
        }
    }
}
   

但这里显示了一些运行时错误:“线程 1:Swift 运行时失败:强制解包一个 nil 值”

请建议我如何解决整个问题。提前致谢!

您可以使用UserDefaults,但您应该使用核心数据或领域以获得更好的性能。 如何使用此代码? // 救球: CartCache.save([购物车])

//获取数据: 让购物车 = CartCache.get()

struct CartCache {
    
        static let key = "CartCache"
    
        static func save(_ value: [CartStruct]!) {
          UserDefaults.standard.set(try? PropertyListEncoder().encode(value), forKey: key)
        }
    
        static func get() -> [CartStruct]! {
          var cartData: User!
          if let data = UserDefaults.standard.value(forKey: key) as? Data {
            cartData = try? PropertyListDecoder().decode([User].self, from: data)
            return cartData!
          } else {
            return []
          }
        }
    
         static func remove() {
            UserDefaults.standard.removeObject(forKey: key)
          }
        }

您应该使用不同于用户默认值的其他数据保存方法。用户默认值主要用于保存姓名、用户名、性别等小信息。我建议您使用 Core Data 而不是用户默认值,这里是 Core Data 的一个非常有用的解释和示例项目。

https://www.raywenderlich.com/7569-getting-started-with-core-data-tutorial

祝你有美好的一天:)

正如许多人提到的,UserDefaults 并不是真正用于存储此类数据的。 来自文档:

The UserDefaults class provides a programmatic interface for interacting with the defaults system. The defaults system allows an app to customize its behavior to match a user’s preferences. For example, you can allow users to specify their preferred units of measurement or media playback speed. Apps store these preferences by assigning values to a set of parameters in a user’s defaults database. The parameters are referred to as defaults because they’re commonly used to determine an app’s default state at startup or the way it acts by default.

但是我觉得这仍然是一个有效的问题,每个 IOS/MacOS 开发人员都应该知道如何使用。

NSUserDefaults 简单易用,但有些事情你必须要明白。

即您只能存储 属性 个列表项。

A default object must be a property list—that is, an instance of (or for collections, a combination of instances of) NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.

这意味着 CartStruct 不能简单地保存在 UserDefaults 中,因为它不是 NSData、NSString、NSNumber、NSDate、NSArray 或 NSDictionary 或它们的组合。

现在使用 UserDefaults 很简单,他们有一个名为标准的应用程序单例。

UserDefaults.standard.setValue("Hello Defaults", forKey: "Hello_Key")
let greeting = UserDefaults.standard.value(forKey: "Hello_Key")

print(greeting!)// prints Hello Dafaults

下一个问题是如何将结构转换为数据。我敢肯定,如果您在这里提出这个问题并 post 您的结构代码,您将得到一个快速简单的解决方案。拥有数据后,您可以将其保存在 UserDefaults 中,或者更好的是保存在文件系统中。事实上,我认为你真正想问的问题是如何保留和检索你的结构数据以在表视图中使用。

是的,我们可以存储在 UserDefaults 中,但与 Core Data 或其他用于添加、更新或删除操作的存储相比,它并不灵活。

下面的代码应该可以工作。

您需要将“CartStruct”设为 Codable

struct CartStruct : Codable {
    var cartItems: jsonstruct
    var cartQuantity: Int
}

接下来,添加这个以将其插入并存储在点击“addToCartbtnTapped”中。(DetailViewController)

 func saveCart(data: CartStruct) {
    let defaults = UserDefaults.standard
    if let cdata = defaults.data(forKey: "cartt") {
        var cartArray = try! PropertyListDecoder().decode([CartStruct].self, from: cdata)
        cartArray.append(data)
        cartCount.text = "\(cartArray.count)"
        if let updatedCart = try? PropertyListEncoder().encode(cartArray) {
            UserDefaults.standard.set(updatedCart, forKey: "cartt")
        }
    }
}

@IBAction func addToCartbtnTapped(_ sender: Any) {
    if let info = detailInfo {
        let cartData = CartStruct(cartItems: info, cartQuantity: 1)
        self.saveCart(data: cartData)
        showAlert()
        (sender as AnyObject).setTitle("Go to Cart", for: .normal)
        addToCartbtn.isUserInteractionEnabled = false
    }
}


@IBAction func cartTappedToNavigate(_ sender: Any) {
        let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
        self.navigationController?.pushViewController(cart!, animated: true)
    }

现在,从您存储的位置获取您的购物车数据。(CartViewController)

override func viewDidLoad() {
        super.viewDidLoad()
        self.getCartData()
    }

 func getCartData() {
        let defaults = UserDefaults.standard
        if let data = defaults.data(forKey: "cartt") {
            cartArray = try! PropertyListDecoder().decode([CartStruct].self, from: data)
            cartTableView.reloadData()
        }
    }