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