【问题标题】:How do I get tableView.reloadData() to work properly with core data?如何让 tableView.reloadData() 与核心数据正常工作?
【发布时间】:2019-12-06 04:07:35
【问题描述】:

当我运行应用程序时,我可以填充我的tableview 中的单元格,但是当我保存(从单独的视图控制器)并返回到tableview controller 时,tableView.reloadData() 被调用但没有任何反应。我使用通知中心重新加载数据,然后再弹出。

TableViewController.swift:

lazy var fetchedResultsController: NSFetchedResultsController<Pet> = {
    let fetchRequest = PersistenceManager.shared.fetchRequest()
    let context = PersistenceManager.shared.context
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    return frc as! NSFetchedResultsController<Pet>
}()

override func viewDidLoad() {
    super.viewDidLoad()
    navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(pushToAddPetViewController))
    tableView.register(MainTableViewCell.self, forCellReuseIdentifier: "cell")
    do {
        try fetchedResultsController.performFetch()
        tableView.reloadData()
    } catch let err {
        print(err)
    }
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
}

@objc func loadList(notification: NSNotification){
    DispatchQueue.main.async {
        self.tableView.reloadData()
    }
}

AddPetVC.swift:

func saveContext() {
    // Inputs saved to coreData
    PersistenceManager.shared.saveContext()
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
    self.navigationController?.popViewController(animated: true)
}

【问题讨论】:

    标签: ios swift core-data tableview


    【解决方案1】:

    您在 viewDidLoad() 中获取了数据,当您返回视图时不会调用该数据。您应该在 viewWillAppear() 中获取数据并从中重新加载或从通知观察者方法 loadList(notification: NSNotification) 重新加载。因此,在 viewWillAppear() 或 loadList(notification: NSNotification) 中添加以下代码:

     do {
            try fetchedResultsController.performFetch()
            tableView.reloadData()
        } catch let err {
            print(err)
        }
    

    【讨论】:

      【解决方案2】:

      当你popViewController回调之前的ViewController时,不会调用viewWillAppear()。

      【讨论】:

        【解决方案3】:

        创建 fetchedResultsController 实例并符合 NSFetchedResultsControllerDelegate。 NSFetchedResultsControllerDelegate 会观察变化并将变化反映在 UI 上

        lazy var fetchedResultsController: NSFetchedResultsController<Pet> = {
                   let fetchRequest = PersistenceManager.shared.fetchRequest()
                   let context = PersistenceManager.shared.context
                   let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
                   frc.delegate = self
        
                   return frc as! NSFetchedResultsController<Pet>
            }()
        

        在你看来DidLoad

        do {
                    try fetchedResultsController.performFetch()
                } catch {
                    let fetchError = error as NSError
                    print("Unable to Save Note")
                    print("\(fetchError), \(fetchError.localizedDescription)")
                }
        

        现在实现 NSFetchedResultsControllerDelegate

        extension YourController: NSFetchedResultsControllerDelegate {
        
            func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
                uiTableView.beginUpdates()
            }
        
            func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
                uiTableView.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 {
                        uiTableView.insertRows(at: [indexPath], with: .fade)
                    }
                    break;
                case .delete:
                    if let indexPath = indexPath {
                        uiTableView.deleteRows(at: [indexPath], with: .fade)
                    }
                    break;
                case .update:
                    if let indexPath = indexPath, let cell = uiTableView.cellForRow(at: indexPath) as? UserCell {
                        configureCell(cell, at: indexPath)
                    }
                    break;
                case .move:
                    if let indexPath = indexPath {
                        uiTableView.deleteRows(at: [indexPath], with: .fade)
                    }
        
                    if let newIndexPath = newIndexPath {
                        uiTableView.insertRows(at: [newIndexPath], with: .fade)
                    }
                    break;
        
                }
            }
        }
        

        实现 UITableViewDataSource & UITableViewDelegate

        extension YourController: UITableViewDataSource, UITableViewDelegate {
        
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                guard let sections = fetchedResultsController.sections else {
                    return 0
                }
        
                let sectionInfo = sections[section]
                return sectionInfo.numberOfObjects
            }
            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                let cell = tableView.dequeueReusableCell(withIdentifier: "PetCell", for: indexPath) as! Pet
                configureCell(cell, at: indexPath)
        
                return cell
            }
        
            func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                let pet = fetchedResultsController.object(at: indexPath)
        
            }
        
            func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
                return true
            }
        
            func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
                if (editingStyle == .delete) {
                    // handle delete (by removing the data from your array and updating the tableview)
                    //let user = viewModel.user(for: indexPath.row)
                    let pet = fetchedResultsController.object(at: indexPath)
                    //Delete pet and reload table
                }
            }
        
            func configureCell(_ cell: Pet, at indexPath: IndexPath) {
                let pet = fetchedResultsController.object(at: indexPath)
        }
        

        更多细节和代码请关注演示项目 https://github.com/rheyansh/CoreDataDemo

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-08
          • 2020-08-27
          • 2018-06-11
          相关资源
          最近更新 更多