mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-16 05:56:50 +01:00
added thread safety checks to ListMonitor to prevent deadlocks after calling refetch()
This commit is contained in:
@@ -114,6 +114,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
*/
|
||||
public subscript(safeSectionIndex sectionIndex: Int, safeItemIndex itemIndex: Int) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
guard let sections = self.fetchedResultsController.sections
|
||||
where sectionIndex < sections.count else {
|
||||
|
||||
@@ -136,6 +141,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
*/
|
||||
public subscript(indexPath: NSIndexPath) -> T {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return self.fetchedResultsController.objectAtIndexPath(indexPath) as! T
|
||||
}
|
||||
|
||||
@@ -181,6 +191,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func objectsInAllSections() -> [T] {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return (self.fetchedResultsController.fetchedObjects as? [T]) ?? []
|
||||
}
|
||||
|
||||
@@ -193,6 +208,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func objectsInSection(section: Int) -> [T] {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return (self.fetchedResultsController.sections?[section].objects as? [T]) ?? []
|
||||
}
|
||||
|
||||
@@ -205,6 +225,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return (self.fetchedResultsController.sections?[section].objects as? [T]) ?? []
|
||||
}
|
||||
|
||||
@@ -216,6 +241,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func numberOfSections() -> Int {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return self.fetchedResultsController.sections?.count ?? 0
|
||||
}
|
||||
|
||||
@@ -227,6 +257,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func numberOfObjects() -> Int {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return self.fetchedResultsController.fetchedObjects?.count ?? 0
|
||||
}
|
||||
|
||||
@@ -263,6 +298,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return self.fetchedResultsController.sections![section]
|
||||
}
|
||||
|
||||
@@ -275,6 +315,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func sectionInfoAtIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
guard let sections = self.fetchedResultsController.sections
|
||||
where section < sections.count else {
|
||||
|
||||
@@ -293,6 +338,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func indexOf(object: T) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return (self.fetchedResultsController.fetchedObjects as? [T] ?? []).indexOf(object)
|
||||
}
|
||||
|
||||
@@ -305,6 +355,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
@warn_unused_result
|
||||
public func indexPathOf(object: T) -> NSIndexPath? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || NSThread.isMainThread(),
|
||||
"Attempted to access a \(typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
|
||||
return self.fetchedResultsController.indexPathForObject(object)
|
||||
}
|
||||
|
||||
@@ -766,6 +821,11 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
*/
|
||||
public func refetch(fetchClauses: [FetchClause]) {
|
||||
|
||||
CoreStore.assert(
|
||||
NSThread.isMainThread(),
|
||||
"Attempted to refetch a \(typeName(self)) outside the main thread."
|
||||
)
|
||||
|
||||
self.isPendingRefetch = true
|
||||
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||
@@ -780,19 +840,39 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.fetchedResultsControllerDelegate.fetchedResultsController = nil
|
||||
|
||||
let fetchRequest = strongSelf.fetchedResultsController.fetchRequest
|
||||
for clause in fetchClauses {
|
||||
|
||||
clause.applyToFetchRequest(fetchRequest)
|
||||
}
|
||||
|
||||
try! strongSelf.fetchedResultsController.performFetch()
|
||||
strongSelf.isPendingRefetch = false
|
||||
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||
ListMonitorDidRefetchListNotification,
|
||||
object: strongSelf
|
||||
)
|
||||
GCDQueue.Utility.async {
|
||||
|
||||
guard let strongSelf = self else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try! strongSelf.fetchedResultsController.performFetch()
|
||||
|
||||
GCDQueue.Main.async { () -> Void in
|
||||
|
||||
guard let strongSelf = self else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.fetchedResultsControllerDelegate.fetchedResultsController = strongSelf.fetchedResultsController
|
||||
strongSelf.isPendingRefetch = false
|
||||
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||
ListMonitorDidRefetchListNotification,
|
||||
object: strongSelf
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,6 +888,9 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .ManagedObjectResultType
|
||||
fetchRequest.fetchBatchSize = 20
|
||||
fetchRequest.includesPendingChanges = false
|
||||
fetchRequest.shouldRefreshRefetchedObjects = true
|
||||
|
||||
for clause in fetchClauses {
|
||||
|
||||
|
||||
@@ -172,6 +172,8 @@ public final class ObjectMonitor<T: NSManagedObject> {
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .ManagedObjectResultType
|
||||
fetchRequest.sortDescriptors = []
|
||||
fetchRequest.includesPendingChanges = false
|
||||
fetchRequest.shouldRefreshRefetchedObjects = true
|
||||
|
||||
let originalObjectID = object.objectID
|
||||
Where("SELF", isEqualTo: originalObjectID).applyToFetchRequest(fetchRequest)
|
||||
|
||||
Reference in New Issue
Block a user