如何将现有的单例表视图数据保存在核心数据中?

Posted

技术标签:

【中文标题】如何将现有的单例表视图数据保存在核心数据中?【英文标题】:How to save existing singleton table view data in core data? 【发布时间】:2019-06-08 19:27:05 【问题描述】:

我的项目中有像 var fromSharedFood = SingletonCart.sharedFood.food 这样的单件购物车。我正在从 MainVC 获取所有食物数据到 DetailVC -> MyCartVC。我在 MainVC 中有表格视图。我想将 MainVC 表视图数据保存到 CoreData。

我的项目离线。现在,它与 web api 通信。我使用 Singleton 进行从 MainVC 到 DetailVC 到 MyCartVC 的数据转换。现在,如果用户登录系统,我需要用核心数据等保存他/她的购物车。 即用户将食物添加到购物车并注销他/她的购物车必须在重新登录时保存。

我尝试使用 UserDefaults self.myCartUserDefaults.set(myCartTableView.dataSource, forKey: "userCart"),但这没有意义。 我为食物名称和价格创建了 CoreData 实体。

这是 MyCartVC

import UIKit
import CoreData

class MyCartViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

var fromDetailFoodNames = ""
var fromDetailFoodPrices = ""
var backgroundView: UIView?

@IBOutlet weak var myCartTableView: UITableView!
@IBOutlet weak var totalPriceLabel: UILabel!
private let persistentContainer = NSPersistentContainer(name: "MyCartData")

var food: Food?

var fromSharedFood = SingletonCart.sharedFood.food

//TODO: - Approve my  cart
@IBAction func approveCart(_ sender: Any) 


override func viewDidLoad() 
    super.viewDidLoad()    
    self.tabBarController?.tabBar.isHidden = false
    myCartTableView.reloadData()




override func viewWillAppear(_ animated: Bool) 

  self.myCartTableView.reloadData()

    if foodCoreData.count == 0 

        myCartTableView.setEmptyView(title: "Sepetinizde ürün bulunmamaktadır", message: "Seçtiğiniz yemekler burada listelenir.")
    
    else 
        myCartTableView.restore()
        self.tabBarController?.viewControllers![1].tabBarItem.badgeValue = "\(foodCoreData.count)"
        guard let appDelegate =
            UIApplication.shared.delegate as? AppDelegate else 
                return
        

        let managedContext =
            appDelegate.persistentContainer.viewContext

        let fetchRequest =
            NSFetchRequest<NSManagedObject>(entityName: "MyCartData")

        do 
            foodCoreData = try managedContext.fetch(fetchRequest)
            print("COREDATA FETCH EDİLDİ")
         catch let error as NSError 
            print("Could not fetch. \(error), \(error.userInfo)")
        
    


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

    if fromSharedFood.count != 0 
        tableView.restore()
    

    return fromSharedFood.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let foodName = fromSharedFood[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "myCartCell", for: indexPath) as! MyCartTableViewCell
    cell.myCartFoodNameLabel.text = foodName.ProductTitle
    self.tabBarController?.viewControllers![1].tabBarItem.badgeValue = "\(fromSharedFood.count)"
    cell.myCartFoodPriceLabel.text = foodName.PriceString
    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 
        fromSharedFood.remove(at: indexPath.row)
        tableView.beginUpdates()
        tableView.deleteRows(at: [indexPath], with: .automatic)

         if fromSharedFood.count == 0 
                myCartTableView.reloadData()
                self.tabBarController?.viewControllers![1].tabBarItem.badgeValue = nil 
            else 
                self.tabBarController?.viewControllers![1].tabBarItem.badgeValue = "\(fromSharedFood.count)"
            
            myCartTableView.restore()
        
        tableView.endUpdates()
    
    
    

编辑:

我的数据来自带有addBasket() 按钮的DetailVC。首先,我尝试将 DetailVC 标签数据保存到核心数据。之后从 MyCartVC 获取但没有得到任何响应。

这里是 DetailVC:

import UIKit
import CoreData

class DetailViewController: UIViewController, TagListViewDelegate 

@IBOutlet weak var foodTitle: UILabel!
@IBOutlet weak var foodSubTitle: UILabel!
@IBOutlet weak var foodPrice: UILabel!
@IBOutlet weak var foodQuantity: UILabel!
@IBOutlet weak var detailFoodImage: UIImageView!

@IBOutlet weak var tagListView: TagListView!

var window: UIWindow?

var detailFoodName = ""
var detailFoodPrice = ""
var detailPhotoData = String()

var searchFoods: String!
var priceFood: Double!

var foodCoreData: [NSManagedObject] = []
var food: Food?

override func viewDidLoad() 
    super.viewDidLoad()

    foodQuantity.text = "1"

    foodTitle.text = food?.ProductTitle ?? ""
    foodPrice.text = food?.PriceString
    foodSubTitle.text = food?.Description

    tagListView.delegate = self
    setupIngredientsTag()

    self.tabBarController?.tabBar.isHidden = true
    self.navigationController?.navigationItem.title = "Sipariş Detayı"

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier: "FoodOrder")
    self.window?.rootViewController = viewController


func save(foodName: String, foodPrice: String) 

    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else 
            return
    


    let managedContext =
        appDelegate.persistentContainer.viewContext


    let entity =
        NSEntityDescription.entity(forEntityName: "MyCartData",
                                   in: managedContext)!

    let foods = NSManagedObject(entity: entity,
                                insertInto: managedContext)

    foods.setValue(foodName, forKeyPath: "fromDetailFoodNames")
    foods.setValue(foodPrice, forKeyPath: "fromDetailFoodPrices")

    do 
        try managedContext.save()
        foodCoreData.append(foods)
        print("COREDATA KAYDEDİLDİ!")
     catch let error as NSError 
        print("Could not save. \(error), \(error.userInfo)")
    


//TODO:- Add to basket
@IBAction func addBasket(_ sender: Any) 

    SingletonCart.sharedFood.food.append(food!)

    self.performSegue(withIdentifier: "toMyCart", sender: nil)
    self.navigationController?.navigationBar.isHidden = false
    self.tabBarController?.tabBar.isHidden = false
    self.isLoading(true)

    guard let nameToSave = foodTitle.text else  return 
    guard let priceToSave = foodPrice.text else  return 

    self.save(foodName: nameToSave, foodPrice: priceToSave)


@IBAction func cancelButtonClicked(_ sender: UIBarButtonItem) 
    self.navigationController?.popViewController(animated: true)


@IBAction func favoriteButtonClicked(_ sender: UIBarButtonItem) 



override func viewWillAppear(_ animated: Bool) 
    self.navigationController?.navigationBar.isHidden = false



override func viewWillDisappear(_ animated: Bool) 
    self.navigationController?.navigationBar.isHidden = true



SingletonCart

import Foundation
import UIKit

class SingletonCart 
static let sharedFood = SingletonCart()
var food: [Food] = []

private init() 

预期的输出是用户注销时保存他/她的购物车。

【问题讨论】:

你能在上面添加你的SingletonCart 类吗?目前尚不清楚这是如何工作的。 @jake singleton 添加了! 您的问题到底是什么? “怎么救……?”非常模糊,没有描述您的代码存在什么问题。 如果您要使用单例模式,您应该从那里保存您的 CoreData,而不是尝试让单例绕过容器。跨度> 【参考方案1】:

从我所看到的情况来看,您有几个概念是错误的。 Core Data Programming Guide 将帮助您了解它的工作原理以及如何保存数据。

对于您的表格列表,您应该使用 NSFetchedResultsController 而不是自己管理集合。

然后,当从详细视图控制器添加新模型时,您应该创建一个新的背景上下文,创建实体,设置其值,然后保存它。


appDelegate.persistentContainer.performBackgroundTask  (context) in
 let entity =
        NSEntityDescription.entity(forEntityName: "MyCartData",
                                   in: managedContext)!

    let foods = NSManagedObject(entity: entity,
                                insertInto: managedContext)

    foods.setValue(foodName, forKeyPath: "fromDetailFoodNames")
    foods.setValue(foodPrice, forKeyPath: "fromDetailFoodPrices")
    _ = try? managedContext.save()

这会将这个对象保存到持久存储中,它们会刷新您的视图上下文,并且您的 NSFetchedResultsController 将自动更新您的 tableView 控制器

【讨论】:

以上是关于如何将现有的单例表视图数据保存在核心数据中?的主要内容,如果未能解决你的问题,请参考以下文章

Iphone 编程 - 将现有的 sql 表导入到 sqlite 或核心数据

将现有的数据库模式转换为星型模式

如何将现有的 postgres 数据文件夹复制并使用到 docker postgres 容器中

如何使用核心数据访问保存在不同视图控制器中的数组?

如何使用核心数据访问保存在不同视图控制器中的阵列?

如何在“详细”实体视图中为“主/父”实体“保存”(核心数据)?