ListMonitor is now refetch-able. Implement the listMonitorWillRefetch and listMonitorDidRefetch methods of ListObserver and call the refetch(...) method of ListMonitor

This commit is contained in:
John Estropia
2015-09-08 17:21:15 +09:00
parent f47adc12b3
commit 399517e357
3 changed files with 247 additions and 4 deletions

View File

@@ -354,6 +354,32 @@ public final class ListMonitor<T: NSManagedObject> {
observer.listMonitorDidChange(monitor)
}
)
self.registerChangeNotification(
&self.willRefetchListKey,
name: ListMonitorWillRefetchListNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
guard let observer = observer else {
return
}
observer.listMonitorWillRefetch(monitor)
}
)
self.registerChangeNotification(
&self.didRefetchListKey,
name: ListMonitorDidRefetchListNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
guard let observer = observer else {
return
}
observer.listMonitorDidRefetch(monitor)
}
)
}
/**
@@ -402,6 +428,32 @@ public final class ListMonitor<T: NSManagedObject> {
observer.listMonitorDidChange(monitor)
}
)
self.registerChangeNotification(
&self.willRefetchListKey,
name: ListMonitorWillRefetchListNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
guard let observer = observer else {
return
}
observer.listMonitorWillRefetch(monitor)
}
)
self.registerChangeNotification(
&self.didRefetchListKey,
name: ListMonitorDidRefetchListNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
guard let observer = observer else {
return
}
observer.listMonitorDidRefetch(monitor)
}
)
self.registerObjectNotification(
&self.didInsertObjectKey,
@@ -520,6 +572,32 @@ public final class ListMonitor<T: NSManagedObject> {
observer.listMonitorDidChange(monitor)
}
)
self.registerChangeNotification(
&self.willRefetchListKey,
name: ListMonitorWillRefetchListNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
guard let observer = observer else {
return
}
observer.listMonitorWillRefetch(monitor)
}
)
self.registerChangeNotification(
&self.didRefetchListKey,
name: ListMonitorDidRefetchListNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
guard let observer = observer else {
return
}
observer.listMonitorDidRefetch(monitor)
}
)
self.registerObjectNotification(
&self.didInsertObjectKey,
@@ -644,6 +722,8 @@ public final class ListMonitor<T: NSManagedObject> {
let nilValue: AnyObject? = nil
setAssociatedRetainedObject(nilValue, forKey: &self.willChangeListKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.didChangeListKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.willRefetchListKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.didRefetchListKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.didInsertObjectKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.didDeleteObjectKey, inObject: observer)
@@ -654,6 +734,54 @@ public final class ListMonitor<T: NSManagedObject> {
setAssociatedRetainedObject(nilValue, forKey: &self.didDeleteSectionKey, inObject: observer)
}
/**
Asks the `ListMonitor` to refetch its objects using the specified series of `FetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
`refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Note that only specified clauses will be changed; unspecified clauses will use previous values.
*/
public func refetch(fetchClauses: FetchClause...) {
self.refetch(fetchClauses)
}
/**
Asks the `ListMonitor` to refetch its objects using the specified series of `FetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
`refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Note that only specified clauses will be changed; unspecified clauses will use previous values.
*/
public func refetch(fetchClauses: [FetchClause]) {
NSNotificationCenter.defaultCenter().postNotificationName(
ListMonitorWillRefetchListNotification,
object: self
)
self.taskGroup.notify(.Main) { [weak self] () -> Void in
guard let strongSelf = self else {
return
}
let fetchRequest = strongSelf.fetchedResultsController.fetchRequest
for clause in fetchClauses {
clause.applyToFetchRequest(fetchRequest)
}
try! strongSelf.fetchedResultsController.performFetch()
NSNotificationCenter.defaultCenter().postNotificationName(
ListMonitorDidRefetchListNotification,
object: strongSelf
)
}
}
// MARK: Internal
@@ -705,10 +833,13 @@ public final class ListMonitor<T: NSManagedObject> {
private let fetchedResultsController: NSFetchedResultsController
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
private let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
private let taskGroup = GCDGroup()
private weak var parentStack: DataStack?
private var willChangeListKey: Void?
private var didChangeListKey: Void?
private var willRefetchListKey: Void?
private var didRefetchListKey: Void?
private var didInsertObjectKey: Void?
private var didDeleteObjectKey: Void?
@@ -888,6 +1019,7 @@ extension ListMonitor: FetchedResultsControllerHandler {
private func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.taskGroup.enter()
NSNotificationCenter.defaultCenter().postNotificationName(
ListMonitorWillChangeListNotification,
object: self
@@ -900,6 +1032,7 @@ extension ListMonitor: FetchedResultsControllerHandler {
ListMonitorDidChangeListNotification,
object: self
)
self.taskGroup.leave()
}
private func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
@@ -978,6 +1111,8 @@ private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResults
private let ListMonitorWillChangeListNotification = "ListMonitorWillChangeListNotification"
private let ListMonitorDidChangeListNotification = "ListMonitorDidChangeListNotification"
private let ListMonitorWillRefetchListNotification = "ListMonitorWillRefetchListNotification"
private let ListMonitorDidRefetchListNotification = "ListMonitorDidRefetchListNotification"
private let ListMonitorDidInsertObjectNotification = "ListMonitorDidInsertObjectNotification"
private let ListMonitorDidDeleteObjectNotification = "ListMonitorDidDeleteObjectNotification"

View File

@@ -58,6 +58,20 @@ public protocol ListObserver: class {
- parameter monitor: the `ListMonitor` monitoring the object being observed
*/
func listMonitorDidChange(monitor: ListMonitor<ListEntityType>)
/**
This method is broadcast from within the `ListMonitor`'s `refetch(...)` method to let observers prepare for the internal `NSFetchedResultsController`'s pending change to its predicate, sort descriptors, etc. Note that the actual refetch will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
- parameter monitor: the `ListMonitor` monitoring the object being observed
*/
func listMonitorWillRefetch(monitor: ListMonitor<ListEntityType>)
/**
After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
- parameter monitor: the `ListMonitor` monitoring the object being observed
*/
func listMonitorDidRefetch(monitor: ListMonitor<ListEntityType>)
}
public extension ListObserver {
@@ -71,6 +85,16 @@ public extension ListObserver {
The default implementation does nothing.
*/
func listMonitorDidChange(monitor: ListMonitor<ListEntityType>) { }
/**
The default implementation does nothing.
*/
func listMonitorWillRefetch(monitor: ListMonitor<ListEntityType>) { }
/**
The default implementation does nothing.
*/
func listMonitorDidRefetch(monitor: ListMonitor<ListEntityType>) { }
}