首页 文章

Swift to-Many Relationship .removeFromMethod()不更新NSFetchedResultsController

提问于
浏览
0

Main Objective: 在第一个视图控制器中,我将点击一个单元格中的一个按钮 - >按钮调用entity.removeFrom " "(_ value:" ")方法 - >自动从第二个视图控制器的表视图中删除相应的单元格 .

What is Occurring: " " ... entity.removeFrom " "(_ value:" ")方法 - >对象被删除,设置为nil,但是NSFetchedResultsController没有删除相应的行 . 让tableview充满空单元格(来自剩余的nil对象)

Question: 如何删除多对多关系中的多个对象并相应地更新NSFetchedResultsController .

About the app 使用swift 3我正在使用标签栏控制器创建一个基本的待办事项列表应用程序 .

第一个标签= tableView of ToDoItem

第二个标签=完成 toDoItems NSFetchedResultsController

核心数据实体: FinishedCollectionToDoItem

FinishedCollectiontodoItems 有一对多的关系(目的地是 ToDoItem

操作顺序:

第一个标签

1)设置 ToDoItem 属性 isFinished

2) FinishedCollection.addToToDoItems(toDoItem)FinishedCollection.removeFromToDoItems(toDoItem)

3)自动更新第二个选项卡 NSFetchedResultsController

PROBLEM: 当我 removeFromToDoItems(toDoItem) 时,NSFetchedResults控制器中的属性设置为nil,而不是完全删除对象(我不一定要完全删除对象)导致空单元格和百万亿个零对象 . 如何在一对多关系中删除多个nil对象,并且只在NSFetchedResults控制器tableview选项卡中完成 toDoItems .

设置numberOfRowsInSection tableview方法时尝试过滤nil对象 . 在这种情况下似乎没有做任何事情

let notNilObjects = sectionInfo.objects.flatMap { 0 }

TableViewDataSource方法

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let sections    = fetchedResultsController?.sections
    let sectionInfo = sections?[section]

    return sectionInfo?.numberOfObjects ?? 1
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell( withIdentifier: "JournalCell", for: indexPath )

    configure(cell, atIndexPath: indexPath)

    return cell
  }

// NSFetchedResultsDelegate方法

fileprivate func configure(_ cell: UITableViewCell, atIndexPath indexPath: IndexPath) {
  guard let selectedObject = fetchedResultsController?.object(at: indexPath) else {
    fatalError("Unexpected Object in FetchedResultsController")
  }

  let toDoItems = selectedObject.dayTasks?.allObjects as! [ToDoItem]
  let toDo = ToDoItems.last

  print(toDo?.name)
}

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

func controller(_ controller               : NSFetchedResultsController<NSFetchRequestResult>,
                didChange sectionInfo      : NSFetchedResultsSectionInfo,
                atSectionIndex sectionIndex: Int,
                for type                   : NSFetchedResultsChangeType) {
  switch type {
  case .insert:
    tableView.insertSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .fade)
  case .delete:
    tableView.deleteSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .fade)
  case .move:
    break
  case .update:
    tableView.reloadData()
  }
}

func controller(_ controller      : NSFetchedResultsController<NSFetchRequestResult>,
                didChange anObject: Any,
                at indexPath      : IndexPath?,
                for type          : NSFetchedResultsChangeType,
                newIndexPath      : IndexPath?) {
  switch type {
  case .insert:
    tableView.insertRows(at: [newIndexPath!], with: .fade)
  case .delete:
    tableView.deleteRows(at: [indexPath!], with: .fade)
  case .update:
    configure(tableView.cellForRow(at: indexPath!)!, atIndexPath: indexPath!)
  case .move:
    tableView.moveRow(at: indexPath!, to: newIndexPath!)
  }
}

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


func initializeFetchedResultsController() {
  let request: NSFetchRequest = ToDoItem.fetchRequest()
  request.sortDescriptors = [ NSSortDescriptor( key: "timestamp", ascending: true ),
                              NSSortDescriptor( key: "isAccomplished", ascending: true) ]

 fetchedResultsController = NSFetchedResultsController( fetchRequest        : request,
                                                       managedObjectContext: CoreDataHelper.context,
                                                       sectionNameKeyPath  : nil,
                                                       cacheName           : nil )
  fetchedResultsController?.delegate = self

  do {
    try fetchedResultsController?.performFetch()
  }
  catch {
    print("Couldn't fetch results controller")
  }
}

2 回答

  • 1

    在你的 initializeFetchedResultsController 方法中添加

    request.predicate = NSPredicate(format: "isFinished = 1")
    
  • 0

    为了过滤从fetchedResultsController获取的NSSet,必须使用NSPredicate并将其分配给NSFetchRequest的 request.predicate 属性 .

    Example

    let request = Entity.fetchRequest()
    
    request.predicate = NSPredicate(format: "isAccomplished == YES")
    

相关问题