获取结果控制器在运行时不更新表

Posted

技术标签:

【中文标题】获取结果控制器在运行时不更新表【英文标题】:Fetched Results Controller doesn't update table at runtime 【发布时间】:2017-06-27 19:59:23 【问题描述】:

我尝试在 swift 3 中使用 fetched results 控制器,但它不起作用。我看到,我的实体通过我自己的 fetch 请求添加到 Core Data,但 frc 没有看到它们。如果我重新启动我的应用程序,新元素将出现在表格中。

FRC 的创建:

func getFRCForChats() -> NSFetchedResultsController<Conversation>
    var fetchedResultsController: NSFetchedResultsController<Conversation>

    let fetchRequest: NSFetchRequest<Conversation> = Conversation.fetchRequest()
    let sortDescriptor = NSSortDescriptor(key: "conversationID", ascending: true)

    fetchRequest.sortDescriptors = [sortDescriptor]

    fetchedResultsController = NSFetchedResultsController<Conversation>(fetchRequest:
        fetchRequest, managedObjectContext: container.viewContext, sectionNameKeyPath: nil, cacheName: nil)

    return fetchedResultsController

使用FRC:

   var fetchedResultsController: NSFetchedResultsController<Conversation>!

override func viewDidLoad() 
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    coreDataService = CoreDataService()
    fetchedResultsController = coreDataService.getFRCForChats()
    fetchedResultsController.delegate = self
    try! fetchedResultsController.performFetch()


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    if(!fetchedResultsController.sections!.isEmpty) 
        if let sectionInfo = fetchedResultsController.sections?[section]
            return sectionInfo.numberOfObjects
         else  print("Unexpected Section") 
    
    return 0


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



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

    //cell.name.text = cells[indexPath.row]

    let conversation = fetchedResultsController.object(at: indexPath)

    if let participants = conversation.participants as? Set<User> 

        conversation.managedObjectContext?.performAndWait 
            for user in participants
                cell.name.text = user.name
                break
            
        
    


    return cell


添加新实体:

var k = 2
@IBAction func createConversation(_ sender: Any) 
    coreDataService.insertConversation(id: k)
    k += 1




 func insertConversation(id: Int) 

    container.performBackgroundTask  (context) in


    let user = User.findOrInsertUser(id: id, name: "Andrew", mobilePhone: 234567, avatar: nil, inContext: context)

    _ = Conversation.findOrInsertConversation(id: id + 100, summa: Double(12+id), users: [user], transactions: [], inContext: context)

        context.saveThrows()
    

    let request: NSFetchRequest<Conversation> = Conversation.fetchRequest()

    container.viewContext.perform 
        if let results = try? self.container.viewContext.fetch(request) 
            print("\(results.count) TweetMs")
            for result in results
                print(result.conversationID, result.summa)
            
        
    

代表:

extension ChatsViewController: NSFetchedResultsControllerDelegate 
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 .delete:
        if let indexPath = indexPath 
            tableView.deleteRows(at: [indexPath], with: .automatic)
        
    case .insert:
        if let newIndexPath = newIndexPath 
            tableView.insertRows(at: [newIndexPath], with: .automatic)
        
    case .move:
        if let indexPath = indexPath 
            tableView.deleteRows(at: [indexPath], with: .automatic)
        

        if let newIndexPath = newIndexPath 
            tableView.insertRows(at: [newIndexPath], with: .automatic)
        
    case .update:
        if let indexPath = indexPath 
            tableView.reloadRows(at: [indexPath], with: .automatic)
        
    


func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) 
    switch type 
    case .delete:
        tableView.deleteSections(IndexSet(integer: sectionIndex),
                                 with: .automatic)
    case .insert:
        tableView.insertSections(IndexSet(integer: sectionIndex),
                                 with: .automatic)
    case .move, .update: break
    


编辑:如果我在每次编辑上下文后调用 performFetch(),表会在不调用委托的情况下重新加载。

【问题讨论】:

【参考方案1】:

正如Apple Docs 所说:

automaticallyMergesChangesFromParent

一个布尔值,指示上下文是否自动合并 保存到其持久存储协调器或父上下文的更改。

尝试将其设置为true

container.viewContext.automaticallyMergesChangesFromParent = true

至少这为我解决了类似的问题。

【讨论】:

以上是关于获取结果控制器在运行时不更新表的主要内容,如果未能解决你的问题,请参考以下文章

NSLog 在 iphone 模拟器上运行时输出到控制台,但在设备上运行时不输出

代码在函数内部时不运行

集合视图标题在运行时不可见

WKWebView 在后台时不运行 JavaScript

Swift Scene Delegate 在首次启动时不运行代码

在 iOS 7 中,导航栏在运行时不可见