Swift,CoreData:当childVC解散时TableView不重新加载数据

Posted

技术标签:

【中文标题】Swift,CoreData:当childVC解散时TableView不重新加载数据【英文标题】:Swift, CoreData: TableView not reloading data when childVC dismissed 【发布时间】:2016-10-26 04:38:16 【问题描述】:

好的,我对此很陌生,并且在阅读许多教程和文章时有点不知所措。并花了几个小时整理类似的问题,但没有解决我自己的问题。我有一个“AddSiteVC”,允许用户添加或删除放入 CoreData 然后显示在我的“MainVC”上的 TableView 中的项目。我的问题是当我按下保存或删除并被解雇回到我的 MainVC onBtnClick 时,TableView 不会更新,直到我离开 MainVC 然后回来。我不知道自己做错了什么,但似乎找不到任何可以解决此问题的方法...我不知道我的问题出在哪里,因此我将包含我的大部分 MainVC 代码以供参考。 任何帮助将不胜感激! 谢谢!

import UIKit
import CoreData

class SitesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate 

@IBOutlet weak var tableView: UITableView!

var controller: NSFetchedResultsController<Sites>!

override func viewDidLoad() 
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    attemptFetch()


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


func configureCell(cell: SitesCell, indexPath: NSIndexPath) 
    let sites = controller.object(at: indexPath as IndexPath)
    cell.configureCell(sites: sites)
    cell.accessoryType = .detailButton


override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if segue.identifier == "AddSiteViewController" 
        if let destination = segue.destination as? AddSiteViewController 
            if let site = sender as? Sites 
                destination.siteToEdit = site
            
        
    


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    if let sections = controller.sections 
        let sectionInfo = sections[section]
        return sectionInfo.numberOfObjects
    
    return 0


func numberOfSections(in tableView: UITableView) -> Int 
    if let sections = controller.sections 
        return sections.count
    
    return 0


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    return 75


func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) 
    if let objs = controller.fetchedObjects, objs.count > 0 
        let site = objs[indexPath.row]
        performSegue(withIdentifier: "AddSiteViewController", sender: site)
    


func attemptFetch() 
    let fetchRequest: NSFetchRequest<Sites> = Sites.fetchRequest()
    let alphebaticalSort = NSSortDescriptor(key: "name", ascending: true)
    fetchRequest.sortDescriptors = [alphebaticalSort]

    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)")
    


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


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)
        
        break
    case.delete:
        if let indexPath = indexPath 
            tableView.deleteRows(at: [indexPath], with: .fade)
        
        break
    case.update:
        if let indexPath = indexPath 
            let cell = tableView.cellForRow(at: indexPath) as! SitesCell
            configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
        
        break
    case.move:
        if let indexPath = indexPath 
            tableView.deleteRows(at: [indexPath], with: .fade)
        
        if let indexPath = newIndexPath 
            tableView.insertRows(at: [indexPath], with: .fade)
        
        break
    


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

【问题讨论】:

将attemptFetch() 放入viewWillAppear() 我按照您的建议将尝试Fetch() 放入 viewWillAppear() 并在 viewDidLoad() 中删除它,它似乎没有任何改变。它仍然不会显示我的新单元格,直到我离开 MainVC 并再次返回一个例外......当我在当前字母排序之后添加一个以字母开头的单元格时。示例 - 我在单元格 1 中有“Home”,在单元格 2 中有“Manns”,如果我在 M 之后添加以字母开头的任何内容,它会立即更新,但 M 之前的任何内容都不会。所以也许我的 NSSortDescriptor 与此有​​关......?但是,这并不能解释为什么删除单元格不会更新... 执行fetch后调用tableview的reloadData()更新表。 我也试过了。返回 tableView 后会立即添加一个新单元格,但它没有显示正确的数据。它在我当前表中显示最后一个字母项目两次,直到我离开 MainVC 并返回,然后它使用正确的信息更新自身。 【参考方案1】:

请在代码中进行以下更改。因为 viewDidLoad 在 vi​​ewcontroller 加载时会被调用。但是根据您的要求,您可以在模态页面中添加一些内容。所以你需要把代码移到viewWillAppear

import UIKit
import CoreData

class SitesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate 

@IBOutlet weak var tableView: UITableView!

var controller: NSFetchedResultsController<Sites>!

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self


    

    override func viewWillAppear(animated: Bool) 
        super.viewWillAppear(animated)
        attemptFetch()
    

【讨论】:

【参考方案2】:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
let cell = tableView.dequeueReusableCell(withIdentifier: "SitesCell", for: indexPath) as! SitesCell
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
return cell 

【讨论】:

你应该解释一下答案。仅仅发布一些代码是没有帮助的。

以上是关于Swift,CoreData:当childVC解散时TableView不重新加载数据的主要内容,如果未能解决你的问题,请参考以下文章

当上下文为 nil 时,Swift Temp CoreData 对象无法设置 ivars

swift CoreData 谓词

Swift/CoreData:-[:]:发送到实例的无法识别的选择器

一对多关系CoreData Swift

保存到 CoreData 似乎有效,但它不是 Swift

使用 FRC Swift 3 更改 CoreData 后 TableView 不更新(reloadData)