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