我从互联网上下载信息并使用数据在Core Data中创建实体。我试图通过与airDate
实体有关系的TVEpisode
实体的TVShow
属性对实体(实体是电视节目,数据来自Trakt)进行排序。如果节目数据的剧集在当前时间的未来日期播出,则TVShow
实体仅与节目有此关系。
所以我想对数据进行排序的方式是:
顶部:显示具有即将发生的集合关系的节目,按airDate
的{{1}}属性排序,按升序排序。
中:显示没有upcomingEpisode
关系但将返回的显示。
底部:显示没有upcomingEpisode
关系且已结束/取消的显示
以下是我遇到的问题。
问题1:使用1 upcomingEpisode
NSFetchedResultsController
使用此let fetchRequest = NSFetchRequest(entityName: "TVShow")
let airDateSort = NSSortDescriptor(key: "upcomingEpisode.airDate", ascending: true)
let titleSort = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [airDateSort, titleSort];
upcomingShowsResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: "upcomingShows")
upcomingShowsResultsController.delegate = self;
var error: NSError? = nil
if (!upcomingShowsResultsController.performFetch(&error)) {
println("Error: \(error?.localizedDescription)")
}
会将所有NSFetchedResultsController
个实体没有TVShow
关系置于顶部,按标题排序,我需要在最底部按标题排序的死显示并返回显示按标题排序在中间。
问题2:使用多个upcomingEpisode
的
NSFetchedResultsController
这些可以满足我的需求,但仅在数据已经下载并且在Core Data中。当应用程序首次启动并下载数据时,它每次都会崩溃,因为部分中的行数与表所期望的不同。我确实操纵了func setupUpcomingShowsFetchedResultsController() {
let fetchRequest = NSFetchRequest(entityName: "TVShow")
let airDateSort = NSSortDescriptor(key: "upcomingEpisode.airDate", ascending: true)
let titleSort = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [airDateSort, titleSort];
let predicate = NSPredicate(format: "upcomingEpisode != nil")
fetchRequest.predicate = predicate
upcomingShowsResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: "upcomingShows")
upcomingShowsResultsController.delegate = self;
var error: NSError? = nil
if (!upcomingShowsResultsController.performFetch(&error)) {
println("Error: \(error?.localizedDescription)")
}
}
func setupReturningShowsFetchedResultsController() {
let fetchRequest = NSFetchRequest(entityName: "TVShow")
let titleSort = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [titleSort];
let predicate = NSPredicate(format: "status == 'returning series'")
let predicate2 = NSPredicate(format: "upcomingEpisode == nil")
fetchRequest.predicate = NSCompoundPredicate.andPredicateWithSubpredicates([predicate!, predicate2!])
returningShowsResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: nil)
returningShowsResultsController.delegate = self;
var error: NSError? = nil
if (!returningShowsResultsController.performFetch(&error)) {
println("Error: \(error?.localizedDescription)")
}
}
func setupDeadShowsFetchedResultsController() {
let fetchRequest = NSFetchRequest(entityName: "TVShow")
let titleSort = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [titleSort]
let endedShowsPredicate = NSPredicate(format: "status == 'ended'")
fetchRequest.predicate = endedShowsPredicate
deadShowsResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: nil)
deadShowsResultsController.delegate = self;
var deadShowsError: NSError? = nil
if (!deadShowsResultsController.performFetch(&deadShowsError)) {
println("Error: \(deadShowsError?.localizedDescription)")
}
}
在NSFetchedResultsControllerDelegate
函数中给出的索引路径,并打印出正在插入的索引。我在任何部分中所做的计数等于表视图所预期的数量,但每次都会抛出错误。这就是我处理多个didChangeObject
NSFetchedResultsController's
如果可以修复崩溃,这将是实现我想要做的最佳方式。
问题3:使用多个数组
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
let section = sectionOfFetchedResultsController(controller)
let indexPathsComputed = [NSIndexPath(forRow: indexPath?.row ?? 0, inSection: section)]
let newIndexPathsComputed = [NSIndexPath(forRow: newIndexPath?.row ?? 0, inSection: section)]
dispatch_async(dispatch_get_main_queue(), { () -> Void in
switch type {
case NSFetchedResultsChangeType.Insert:
self.tableView.insertRowsAtIndexPaths(newIndexPathsComputed, withRowAnimation: .Automatic)
case NSFetchedResultsChangeType.Delete:
self.tableView.deleteRowsAtIndexPaths(indexPathsComputed, withRowAnimation: .Automatic)
case NSFetchedResultsChangeType.Move:
self.tableView.deleteRowsAtIndexPaths(indexPathsComputed, withRowAnimation: .Automatic)
self.tableView.insertRowsAtIndexPaths(newIndexPathsComputed, withRowAnimation: .Automatic)
case NSFetchedResultsChangeType.Update:
if let index = indexPathsComputed[0] {
if let cell = self.tableView.cellForRowAtIndexPath(index) as? ShowTableViewCell {
self.configureCell(cell, indexPath: index)
}
}
else {
println("No cell at index path")
}
}
})
}
这解决了崩溃问题,并在下载数据和下载数据后工作。但是当使用它时,我必须在下载数据时调用func reloadShowsArray() {
let fetchRequest = NSFetchRequest(entityName: "TVShow")
let airDateSort = NSSortDescriptor(key: "upcomingEpisode.airDate", ascending: true)
let titleSort = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [airDateSort, titleSort];
let predicate = NSPredicate(format: "upcomingEpisode != nil")
fetchRequest.predicate = predicate
var error: NSError?
showsArray = coreDataStack.context.executeFetchRequest(fetchRequest, error: &error) as [TVShow]
if let error = error {
println(error)
}
}
func reloadDeadShows() {
let fetchRequest = NSFetchRequest(entityName: "TVShow")
let titleSort = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [titleSort]
let endedShowsPredicate = NSPredicate(format: "status == 'ended'")
fetchRequest.predicate = endedShowsPredicate
var error: NSError?
deadShows = coreDataStack.context.executeFetchRequest(fetchRequest, error: &error) as [TVShow]
if let error = error {
println(error)
}
}
,并且实体只是弹出到没有动画的表视图中,我真的想要来自self.tableView.reloadData()
的动画,因为它看起来更好,是一种更好的体验。我尝试调用insertRowsAtIndexPaths
,然后使用reloadShowsArray()
函数与实体获取索引,以便我可以使用insertRowsAtIndexPaths,但每次为索引返回nil,即使实体是使用上下文保存的在那之前。此外,单元格不会像find()
那么处理这个问题的最佳方法是什么,以及如何通过动画获得所需的排序?
答案 0 :(得分:3)
根据评论,我怀疑三FRC方法会导致问题,因为一个FRC调用controller:didChangeContent
(触发tableView.endUpdates),而另一个FRC仍在处理更新。要解决此问题,请实现一个计数器,该计数器以controller:willChangeContent
递增并在controller:didChangeContent
递减。只有当计数器为零时才应调用tableView beginUpdates
,仅当计数器返回零时才调用endUpdates
。这样,只有当所有三个FRC都已完成处理更新时才会调用endUpdates。
如果可能的话,我也会避免使用dispatch_async
,因为它可能导致表更新发生在beginUpdates / endUpdates周期之外。