我知道這個問題已經過時了,但是我最近遇到了這個問題,並且希望有一個解決方案,無論NSFetchedResultsController
是如何初始化的都可以工作。它基於@ martin-r的回答。
這裏的相應的要旨:https://gist.github.com/stephanecopin/4ad7ed723f9857d96a777d0e7b45d676
import CoreData
extension NSFetchedResultsController {
var predicate: NSPredicate? {
get {
return self.fetchRequest.predicate
}
set {
try! self.setPredicate(newValue)
}
}
var sortDescriptors: [NSSortDescriptor]? {
get {
return self.fetchRequest.sortDescriptors
}
set {
try! self.setSortDescriptors(newValue)
}
}
func setPredicate(predicate: NSPredicate?) throws {
try self.setPredicate(predicate, sortDescriptors: self.sortDescriptors)
}
func setSortDescriptors(sortDescriptors: [NSSortDescriptor]?) throws {
try self.setPredicate(self.predicate, sortDescriptors: sortDescriptors)
}
func setPredicate(predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor]?) throws {
func updateProperties() throws {
if let cacheName = cacheName {
NSFetchedResultsController.deleteCacheWithName(cacheName)
}
self.fetchRequest.predicate = predicate
self.fetchRequest.sortDescriptors = sortDescriptors
try self.performFetch()
}
guard let delegate = self.delegate else {
try updateProperties()
return
}
let previousSections = self.sections ?? []
let previousSectionsCount = previousSections.count
var previousObjects = Set(self.fetchedObjects as? [NSManagedObject] ?? [])
var previousIndexPaths: [NSManagedObject: NSIndexPath] = [:]
previousObjects.forEach {
previousIndexPaths[$0] = self.indexPathForObject($0)
}
try updateProperties()
let newSections = self.sections ?? []
let newSectionsCount = newSections.count
var newObjects = Set(self.fetchedObjects as? [NSManagedObject] ?? [])
var newIndexPaths: [NSManagedObject: NSIndexPath] = [:]
newObjects.forEach {
newIndexPaths[$0] = self.indexPathForObject($0)
}
let updatedObjects = newObjects.intersect(previousObjects)
previousObjects.subtractInPlace(updatedObjects)
newObjects.subtractInPlace(updatedObjects)
var moves: [(object: NSManagedObject, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)] = []
updatedObjects.forEach { updatedObject in
if let previousIndexPath = previousIndexPaths[updatedObject],
let newIndexPath = newIndexPaths[updatedObject]
{
if previousIndexPath != newIndexPath {
moves.append((updatedObject, previousIndexPath, newIndexPath))
}
}
}
if moves.isEmpty && previousObjects.isEmpty && newObjects.isEmpty {
// Nothing really changed
return
}
delegate.controllerWillChangeContent?(self)
moves.forEach {
delegate.controller?(self, didChangeObject: $0.object, atIndexPath: $0.fromIndexPath, forChangeType: .Move, newIndexPath: $0.toIndexPath)
}
let sectionDifference = newSectionsCount - previousSectionsCount
if sectionDifference < 0 {
(newSectionsCount..<previousSectionsCount).forEach {
delegate.controller?(self, didChangeSection: previousSections[$0], atIndex: $0, forChangeType: .Delete)
}
} else if sectionDifference > 0 {
(previousSectionsCount..<newSectionsCount).forEach {
delegate.controller?(self, didChangeSection: newSections[$0], atIndex: $0, forChangeType: .Insert)
}
}
previousObjects.forEach {
delegate.controller?(self, didChangeObject: $0, atIndexPath: previousIndexPaths[$0], forChangeType: .Delete, newIndexPath: nil)
}
newObjects.forEach {
delegate.controller?(self, didChangeObject: $0, atIndexPath: nil, forChangeType: .Insert, newIndexPath: newIndexPaths[$0])
}
delegate.controllerDidChangeContent?(self)
}
}
它暴露在NSFetchedResultsController
,predicate
和sortDescriptors
這反映那些在fetchRequest
找到2個特性。
當這些屬性中的任何一個被設置時,控制器將自動計算更改並通過委託發送它們,所以希望沒有主要的代碼更改。 如果你不想動畫,你仍然可以直接在fetchRequest
本身上設置predicate
或sortDescriptors
。
在委託方法中,您將新謂詞分配給fetchresultscontroller。搜索完成後,您將謂詞分配給原始。網上有一些有用的教程,谷歌。 – Shmidt 2013-02-10 12:28:30
我試圖改變fetchrequest謂詞,但似乎並沒有觸發NSFetchedResultsController的contentDidChange方法 – ItsASecret 2013-02-10 16:03:39
您是否在運行fetchedResultsController之後執行了-performFetchRequest? – Shmidt 2013-02-10 16:26:23