Swift - 保存核心数据后更新 Tableview

Posted

技术标签:

【中文标题】Swift - 保存核心数据后更新 Tableview【英文标题】:Swift - Updating Tableview after saving Core data 【发布时间】:2017-07-13 11:12:58 【问题描述】:

我有一个 mainVC,我在其中执行提取请求。 然后我将获取的数据传递给第二个视图控制器(HomeVc),然后传递给第三个(MyparamsVc) 在第三个 VC 中,我有一个 tableView,它列出了与我在主 VC 中获取的实体具有一对一关系的所有参数

在第四个视图控制器中,我通过表单 (addParamVC) 添加新参数。保存后我关闭控制器并弹出前一个(MyparamsVc)。 我的问题是 tableview 没有用新数据更新,除非我回到我的 HomeVC 然后再次进入 MyparamsVC

我已经实现了 func controllerDidChange an Object,但是由于我没有在同一个控制器中执行提取,所以永远不会调用该函数...如何使用新数据更新 tableview?

MainVc fetchRequest:

 var controller: NSFetchedResultsController<SwimminPool>!

override func viewDidLoad() 
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    attemptFetch()


func attemptFetch() 

    let fetchRequest: NSFetchRequest<SwimminPool> = SwimminPool.fetchRequest()
    let dataSort = NSSortDescriptor(key: "poolCreatedAt", ascending: false)
    fetchRequest.sortDescriptors = [dataSort]


     let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)

    controller.delegate = self
    self.controller = controller

    do 
        try controller.performFetch()
     catch 
        let error = error as NSError
        print("\(error.debugDescription)")
    


addParamVC 保存函数:

var swimmingPoolToConnect: SwimmingPool!
var parameterToEdit: Parameter?

@IBAction func saveBtnPressed(_ sender: Any) 

    var parameter: Parameter

    if parameterToEdit == nil 
        parameter = Parameter(context:context)
     else 
        parameter = parameterToEdit!
    

    if let pH = phTextField.text?.characters.split(separator: ",").joined(separator: ".") 
        if let pHnoComma =  Double(String(pH)) 
        parameter.paramPH = pHnoComma
        
    
  parameter.createdAt = Date()

    swimmingPoolToConnect.addToParameters(parameter)

    ad.saveContext()
    self.presentingViewController?.dismiss(animated: true, completion: nil)

我的参数VC:

 var parameters = [Parameter]()
var swimmingPool: SwimmingPool! 
    didSet 
        parameters = (swimmingPool.parameters?.allObjects as! [Parameter]).sorted(by: $0.createdAt! > $1.createdAt!)
    


var controller: NSFetchedResultsController<Parameter>?

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "ParamCell", for: indexPath) as! ParamCell
    configureCell(cell: cell, indexPath: indexPath)
    return cell


 func configureCell(cell: ParamCell, indexPath: IndexPath) 

    let param = parameters[indexPath.row]
    cell.configureCell(parameter: param)


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

  let  parameterToPass = parameters[indexPath.row]
        DispatchQueue.main.async  () -> Void in
            self.performSegue(withIdentifier: "MyParameterDetail", sender: parameterToPass)
        

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
      return parameters.count
   
func numberOfSections(in tableView: UITableView) -> Int 
    return 1


  //Never enter these func

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) 
    tableView.beginUpdates()


func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) 
    tableView.endUpdates()


func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) 

    switch(type)
    case.insert:
        if let indexPath = newIndexPath
            tableView.insertRows(at: [indexPath], with: .fade)

        

    case.delete:
        if let indexPath = indexPath
            tableView.deleteRows(at: [indexPath], with: .fade)
        

    case.update:
        if let indexPath = indexPath
            let cell = tableView.cellForRow(at: indexPath) as! ParamCell
            configureCell(cell: cell, indexPath: indexPath)
        

    case.move:
        if let indexPath = indexPath
            tableView.deleteRows(at: [indexPath], with: .fade)
        
        if let indexPath = newIndexPath
            tableView.insertRows(at: [indexPath], with: .fade)
        
    

【问题讨论】:

【参考方案1】:

由于您有对呈现视图控制器的引用,因此将项目添加到 parameters 数组并从 addParamVCMyparamsVC 中插入一行

ad.saveContext()
let paramsVC = self.presentingViewController as! MyparamsVC
let lastRow = paramsVC.parameters.count
paramsVC.parameters.append(parameter)
paramsVC.tableView.insertRows(at: [NSIndexPath(row: lastRow, section: 0)], with: .none)
paramsVC.dismiss(animated: true, completion: nil)

甚至在dismiss方法的完成处理程序中

ad.saveContext()
let paramsVC = self.presentingViewController as! MyparamsVC

paramsVC.dismiss(animated: true) 
    let lastRow = paramsVC.parameters.count
    paramsVC.parameters.append(parameter)
    paramsVC.tableView.insertRows(at: [NSIndexPath(row: lastRow, section: 0)], with: .none)

【讨论】:

不敢相信你又一次救了我...自从两天以来我才试图实现这一目标...。我可以将它作为第一个元素插入而不是 lastRow 吗? 是的,改为追加insert(parameter, at:0)IndexPath(row:0, section:0) 我欠你很多时间!!!多亏了你,我已经完成了最让我担心的部分,一切都很完美!!谢谢!在最后的日子里……你确实救了我! :) 不客气。在没有像 NSFetchedResultsController 这样的帮助器的情况下在表视图中显示 CoreData 时,您必须同时管理三件事:Core Data 堆栈、数据源数组和用户界面(表视图)。 两个月前我开始使用 swift 进行编码.... 全新... :) 感谢您的帮助,我学到了很多东西,这很棒! :) 我会珍惜所有这些建议【参考方案2】:

你可以在保存到核心数据后刷新视图控制器

 self.viewDidLoad()
  self.viewWillAppear(true)

或者你可以像这样重新加载tableview

self.tableView.reloadData()

【讨论】:

您已在 mainvc 中获取数据,但您将数据保存在第三个 vc 中并希望在 MyparamsVC 中查看。对 我在 mainVC 中获取游泳池,然后将其传递给 myparamsVC。 myparamsVC 与 AddParamVC 有一个 segue,我在其中保存参数。保存后,我会在 myparamsVC 中显示它们 保存后可以追加参数 在 AddParamVC 你的意思是? 对不起,但我是 swift 新手……我在 AddparamVC 中没有参数数组……我只是从文本字段中分配值并保存它们。 var参数:Parameter----> parameter.paramPH = pHnoComma.....

以上是关于Swift - 保存核心数据后更新 Tableview的主要内容,如果未能解决你的问题,请参考以下文章

Swift UI:使用数组中的随机元素更新视图

快速更新核心数据对象 3

尝试从响应 Swift Alamofire 将数据保存到核心数据时崩溃

如何在swift中保存核心数据中的值

保存核心数据对象后,UISplitView 详细信息未更新

Swift 3 - 从核心数据中获取价值