mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-14 05:03:31 +01:00
Improve refetch method (may fix #118)
This commit is contained in:
@@ -43,7 +43,10 @@ private struct Static {
|
||||
|
||||
didSet {
|
||||
|
||||
self.palettes.refetch(self.filter.whereClause())
|
||||
self.palettes.refetch(
|
||||
self.filter.whereClause(),
|
||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,9 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
@nonobjc
|
||||
internal var enabled = true
|
||||
|
||||
@nonobjc
|
||||
internal let taskGroup = DispatchGroup()
|
||||
|
||||
@nonobjc
|
||||
internal weak var handler: FetchedResultsControllerHandler?
|
||||
|
||||
@@ -78,6 +81,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
@objc
|
||||
dynamic func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
|
||||
self.taskGroup.enter()
|
||||
guard self.enabled else {
|
||||
|
||||
return
|
||||
@@ -92,6 +96,10 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
@objc
|
||||
dynamic func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
|
||||
defer {
|
||||
|
||||
self.taskGroup.leave()
|
||||
}
|
||||
guard self.enabled else {
|
||||
|
||||
return
|
||||
|
||||
@@ -555,7 +555,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
`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.
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Important: Starting CoreStore 4.0, all `FetchClause`s required by the `ListMonitor` should be provided in the arguments list of `refetch(...)`.
|
||||
*/
|
||||
public func refetch(_ fetchClauses: FetchClause...) {
|
||||
|
||||
@@ -567,7 +567,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
`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.
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Important: Starting CoreStore 4.0, all `FetchClause`s required by the `ListMonitor` should be provided in the arguments list of `refetch(...)`.
|
||||
*/
|
||||
public func refetch(_ fetchClauses: [FetchClause]) {
|
||||
|
||||
@@ -946,8 +946,12 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
return
|
||||
}
|
||||
|
||||
self.fetchedResultsControllerDelegate.enabled = false
|
||||
self.applyFetchClauses(self.fetchedResultsController.fetchRequest)
|
||||
let (newFetchedResultsController, newFetchedResultsControllerDelegate) = ListMonitor.recreateFetchedResultsController(
|
||||
context: self.fetchedResultsController.managedObjectContext,
|
||||
from: self.from,
|
||||
sectionBy: self.sectionBy,
|
||||
applyFetchClauses: self.applyFetchClauses
|
||||
)
|
||||
|
||||
self.transactionQueue.async { [weak self] in
|
||||
|
||||
@@ -956,16 +960,21 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
return
|
||||
}
|
||||
|
||||
try! self.fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
|
||||
DispatchQueue.main.async { [weak self] () -> Void in
|
||||
try! newFetchedResultsController.performFetchFromSpecifiedStores()
|
||||
self.fetchedResultsControllerDelegate.taskGroup.notify(queue: .main) {
|
||||
|
||||
self.fetchedResultsControllerDelegate.enabled = false
|
||||
}
|
||||
newFetchedResultsControllerDelegate.taskGroup.notify(queue: .main) { [weak self] () -> Void in
|
||||
|
||||
guard let `self` = self else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.fetchedResultsControllerDelegate.enabled = true
|
||||
(self.fetchedResultsController, self.fetchedResultsControllerDelegate) = (newFetchedResultsController, newFetchedResultsControllerDelegate)
|
||||
newFetchedResultsControllerDelegate.handler = self
|
||||
|
||||
self.isPendingRefetch = false
|
||||
|
||||
NotificationCenter.default.post(
|
||||
@@ -986,7 +995,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
fileprivate let fetchedResultsController: CoreStoreFetchedResultsController
|
||||
fileprivate var fetchedResultsController: CoreStoreFetchedResultsController
|
||||
fileprivate let taskGroup = DispatchGroup()
|
||||
fileprivate let sectionIndexTransformer: (_ sectionName: KeyPath?) -> String?
|
||||
|
||||
@@ -1005,7 +1014,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
private var didInsertSectionKey: Void?
|
||||
private var didDeleteSectionKey: Void?
|
||||
|
||||
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
|
||||
private var fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
|
||||
private var observerForWillChangePersistentStore: NotificationObserver!
|
||||
private var observerForDidChangePersistentStore: NotificationObserver!
|
||||
private let transactionQueue: DispatchQueue
|
||||
@@ -1032,9 +1041,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<ObjectType>) -> Void)?) {
|
||||
|
||||
self.isSectioned = (sectionBy != nil)
|
||||
private static func recreateFetchedResultsController(context: NSManagedObjectContext, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) -> (controller: CoreStoreFetchedResultsController, delegate: FetchedResultsControllerDelegate) {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
fetchRequest.fetchLimit = 0
|
||||
@@ -1052,9 +1059,25 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
|
||||
let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
|
||||
fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController
|
||||
|
||||
self.fetchedResultsController = fetchedResultsController
|
||||
self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
|
||||
return (fetchedResultsController, fetchedResultsControllerDelegate)
|
||||
}
|
||||
|
||||
private let from: From<ObjectType>
|
||||
private let sectionBy: SectionBy?
|
||||
|
||||
private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<ObjectType>) -> Void)?) {
|
||||
|
||||
self.isSectioned = (sectionBy != nil)
|
||||
self.from = from
|
||||
self.sectionBy = sectionBy
|
||||
(self.fetchedResultsController, self.fetchedResultsControllerDelegate) = ListMonitor.recreateFetchedResultsController(
|
||||
context: context,
|
||||
from: from,
|
||||
sectionBy: sectionBy,
|
||||
applyFetchClauses: applyFetchClauses
|
||||
)
|
||||
|
||||
if let sectionIndexTransformer = sectionBy?.sectionIndexTransformer {
|
||||
|
||||
@@ -1066,9 +1089,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
}
|
||||
self.transactionQueue = transactionQueue
|
||||
self.applyFetchClauses = applyFetchClauses
|
||||
|
||||
fetchedResultsControllerDelegate.handler = self
|
||||
fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController
|
||||
self.fetchedResultsControllerDelegate.handler = self
|
||||
|
||||
guard let coordinator = context.parentStack?.coordinator else {
|
||||
|
||||
@@ -1129,7 +1150,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
transactionQueue.async {
|
||||
|
||||
try! fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
try! self.fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
self.taskGroup.notify(queue: .main) {
|
||||
|
||||
createAsynchronously(self)
|
||||
@@ -1138,7 +1159,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
}
|
||||
else {
|
||||
|
||||
try! fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
try! self.fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1326,12 +1347,15 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
||||
}
|
||||
|
||||
internal func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
|
||||
|
||||
defer {
|
||||
|
||||
self.taskGroup.leave()
|
||||
}
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name.listMonitorDidChangeList,
|
||||
object: self
|
||||
)
|
||||
self.taskGroup.leave()
|
||||
}
|
||||
|
||||
internal func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String?) -> String? {
|
||||
|
||||
Reference in New Issue
Block a user