mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-04-21 08:21:21 +02:00
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:
@@ -354,6 +354,32 @@ public final class ListMonitor<T: NSManagedObject> {
|
|||||||
observer.listMonitorDidChange(monitor)
|
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)
|
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.registerObjectNotification(
|
||||||
&self.didInsertObjectKey,
|
&self.didInsertObjectKey,
|
||||||
@@ -520,6 +572,32 @@ public final class ListMonitor<T: NSManagedObject> {
|
|||||||
observer.listMonitorDidChange(monitor)
|
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.registerObjectNotification(
|
||||||
&self.didInsertObjectKey,
|
&self.didInsertObjectKey,
|
||||||
@@ -644,6 +722,8 @@ public final class ListMonitor<T: NSManagedObject> {
|
|||||||
let nilValue: AnyObject? = nil
|
let nilValue: AnyObject? = nil
|
||||||
setAssociatedRetainedObject(nilValue, forKey: &self.willChangeListKey, inObject: observer)
|
setAssociatedRetainedObject(nilValue, forKey: &self.willChangeListKey, inObject: observer)
|
||||||
setAssociatedRetainedObject(nilValue, forKey: &self.didChangeListKey, 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.didInsertObjectKey, inObject: observer)
|
||||||
setAssociatedRetainedObject(nilValue, forKey: &self.didDeleteObjectKey, 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)
|
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
|
// MARK: Internal
|
||||||
|
|
||||||
@@ -705,10 +833,13 @@ public final class ListMonitor<T: NSManagedObject> {
|
|||||||
private let fetchedResultsController: NSFetchedResultsController
|
private let fetchedResultsController: NSFetchedResultsController
|
||||||
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
|
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
|
||||||
private let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
|
private let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
|
||||||
|
private let taskGroup = GCDGroup()
|
||||||
private weak var parentStack: DataStack?
|
private weak var parentStack: DataStack?
|
||||||
|
|
||||||
private var willChangeListKey: Void?
|
private var willChangeListKey: Void?
|
||||||
private var didChangeListKey: Void?
|
private var didChangeListKey: Void?
|
||||||
|
private var willRefetchListKey: Void?
|
||||||
|
private var didRefetchListKey: Void?
|
||||||
|
|
||||||
private var didInsertObjectKey: Void?
|
private var didInsertObjectKey: Void?
|
||||||
private var didDeleteObjectKey: Void?
|
private var didDeleteObjectKey: Void?
|
||||||
@@ -888,6 +1019,7 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
|||||||
|
|
||||||
private func controllerWillChangeContent(controller: NSFetchedResultsController) {
|
private func controllerWillChangeContent(controller: NSFetchedResultsController) {
|
||||||
|
|
||||||
|
self.taskGroup.enter()
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||||
ListMonitorWillChangeListNotification,
|
ListMonitorWillChangeListNotification,
|
||||||
object: self
|
object: self
|
||||||
@@ -900,6 +1032,7 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
|||||||
ListMonitorDidChangeListNotification,
|
ListMonitorDidChangeListNotification,
|
||||||
object: self
|
object: self
|
||||||
)
|
)
|
||||||
|
self.taskGroup.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
|
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 ListMonitorWillChangeListNotification = "ListMonitorWillChangeListNotification"
|
||||||
private let ListMonitorDidChangeListNotification = "ListMonitorDidChangeListNotification"
|
private let ListMonitorDidChangeListNotification = "ListMonitorDidChangeListNotification"
|
||||||
|
private let ListMonitorWillRefetchListNotification = "ListMonitorWillRefetchListNotification"
|
||||||
|
private let ListMonitorDidRefetchListNotification = "ListMonitorDidRefetchListNotification"
|
||||||
|
|
||||||
private let ListMonitorDidInsertObjectNotification = "ListMonitorDidInsertObjectNotification"
|
private let ListMonitorDidInsertObjectNotification = "ListMonitorDidInsertObjectNotification"
|
||||||
private let ListMonitorDidDeleteObjectNotification = "ListMonitorDidDeleteObjectNotification"
|
private let ListMonitorDidDeleteObjectNotification = "ListMonitorDidDeleteObjectNotification"
|
||||||
|
|||||||
@@ -58,6 +58,20 @@ public protocol ListObserver: class {
|
|||||||
- parameter monitor: the `ListMonitor` monitoring the object being observed
|
- parameter monitor: the `ListMonitor` monitoring the object being observed
|
||||||
*/
|
*/
|
||||||
func listMonitorDidChange(monitor: ListMonitor<ListEntityType>)
|
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 {
|
public extension ListObserver {
|
||||||
@@ -71,6 +85,16 @@ public extension ListObserver {
|
|||||||
The default implementation does nothing.
|
The default implementation does nothing.
|
||||||
*/
|
*/
|
||||||
func listMonitorDidChange(monitor: ListMonitor<ListEntityType>) { }
|
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>) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,41 @@ import CoreStore
|
|||||||
|
|
||||||
private struct Static {
|
private struct Static {
|
||||||
|
|
||||||
|
enum Filter: String {
|
||||||
|
|
||||||
|
case All = "All Colors"
|
||||||
|
case Light = "Light Colors"
|
||||||
|
case Dark = "Dark Colors"
|
||||||
|
|
||||||
|
func next() -> Filter {
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
|
||||||
|
case All: return .Light
|
||||||
|
case Light: return .Dark
|
||||||
|
case Dark: return .All
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func whereClause() -> Where {
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
|
||||||
|
case .All: return Where(true)
|
||||||
|
case .Light: return Where("brightness >= 0.9")
|
||||||
|
case .Dark: return Where("brightness <= 0.4")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var filter = Filter.All {
|
||||||
|
|
||||||
|
didSet {
|
||||||
|
|
||||||
|
self.palettes.refetch(self.filter.whereClause())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static let palettes: ListMonitor<Palette> = {
|
static let palettes: ListMonitor<Palette> = {
|
||||||
|
|
||||||
try! CoreStore.addSQLiteStoreAndWait(
|
try! CoreStore.addSQLiteStoreAndWait(
|
||||||
@@ -47,7 +82,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
self.navigationItem.leftBarButtonItems = [
|
let navigationItem = self.navigationItem
|
||||||
|
navigationItem.leftBarButtonItems = [
|
||||||
self.editButtonItem(),
|
self.editButtonItem(),
|
||||||
UIBarButtonItem(
|
UIBarButtonItem(
|
||||||
barButtonSystemItem: .Trash,
|
barButtonSystemItem: .Trash,
|
||||||
@@ -55,11 +91,22 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
action: "resetBarButtonItemTouched:"
|
action: "resetBarButtonItemTouched:"
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(
|
|
||||||
barButtonSystemItem: .Add,
|
let filterBarButton = UIBarButtonItem(
|
||||||
|
title: Static.filter.rawValue,
|
||||||
|
style: .Plain,
|
||||||
target: self,
|
target: self,
|
||||||
action: "addBarButtonItemTouched:"
|
action: "filterBarButtonItemTouched:"
|
||||||
)
|
)
|
||||||
|
navigationItem.rightBarButtonItems = [
|
||||||
|
UIBarButtonItem(
|
||||||
|
barButtonSystemItem: .Add,
|
||||||
|
target: self,
|
||||||
|
action: "addBarButtonItemTouched:"
|
||||||
|
),
|
||||||
|
filterBarButton
|
||||||
|
]
|
||||||
|
self.filterBarButton = filterBarButton
|
||||||
|
|
||||||
Static.palettes.addObserver(self)
|
Static.palettes.addObserver(self)
|
||||||
}
|
}
|
||||||
@@ -150,6 +197,18 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
self.tableView.endUpdates()
|
self.tableView.endUpdates()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func listMonitorWillRefetch(monitor: ListMonitor<Palette>) {
|
||||||
|
|
||||||
|
self.setTableEnabled(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listMonitorDidRefetch(monitor: ListMonitor<Palette>) {
|
||||||
|
|
||||||
|
self.filterBarButton?.title = Static.filter.rawValue
|
||||||
|
self.tableView.reloadData()
|
||||||
|
self.setTableEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: ListObjectObserver
|
// MARK: ListObjectObserver
|
||||||
|
|
||||||
@@ -195,6 +254,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
|
private var filterBarButton: UIBarButtonItem?
|
||||||
|
|
||||||
@IBAction private dynamic func resetBarButtonItemTouched(sender: AnyObject?) {
|
@IBAction private dynamic func resetBarButtonItemTouched(sender: AnyObject?) {
|
||||||
|
|
||||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||||
@@ -204,6 +265,11 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction private dynamic func filterBarButtonItemTouched(sender: AnyObject?) {
|
||||||
|
|
||||||
|
Static.filter = Static.filter.next()
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction private dynamic func addBarButtonItemTouched(sender: AnyObject?) {
|
@IBAction private dynamic func addBarButtonItemTouched(sender: AnyObject?) {
|
||||||
|
|
||||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||||
@@ -214,5 +280,23 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
transaction.commit()
|
transaction.commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func setTableEnabled(enabled: Bool) {
|
||||||
|
|
||||||
|
UIView.animateWithDuration(
|
||||||
|
0.2,
|
||||||
|
delay: 0,
|
||||||
|
options: .BeginFromCurrentState,
|
||||||
|
animations: { () -> Void in
|
||||||
|
|
||||||
|
if let tableView = self.tableView {
|
||||||
|
|
||||||
|
tableView.alpha = enabled ? 1.0 : 0.5
|
||||||
|
tableView.userInteractionEnabled = enabled
|
||||||
|
}
|
||||||
|
},
|
||||||
|
completion: nil
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user