mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-24 18:31:17 +01:00
NSManagedObject features are now fully supported for CoreStoreObject types. MacOSX 10.12 onwards now support ListMonitors and ObjectMonitors
This commit is contained in:
@@ -27,10 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CoreStore
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension CoreStore {
|
||||
|
||||
/**
|
||||
@@ -144,5 +143,3 @@ public extension CoreStore {
|
||||
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,10 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - DataStack
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension DataStack {
|
||||
|
||||
/**
|
||||
@@ -220,5 +219,3 @@ public extension DataStack {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ListMonitor
|
||||
|
||||
/**
|
||||
@@ -68,7 +66,8 @@ import CoreData
|
||||
```
|
||||
In the example above, both `person1` and `person2` will contain the object at section=2, index=3.
|
||||
*/
|
||||
public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
@available(OSX 10.12, *)
|
||||
public final class ListMonitor<T: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Public (Accessors)
|
||||
|
||||
@@ -80,7 +79,15 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
*/
|
||||
public subscript(index: Int) -> T {
|
||||
|
||||
return self.objectsInAllSections()[index]
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
if self.isSectioned {
|
||||
|
||||
return T.cs_fromRaw(object: self.fetchedResultsController.fetchedObjects![index])
|
||||
}
|
||||
return self[0, index]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,12 +98,16 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
*/
|
||||
public subscript(safeIndex index: Int) -> T? {
|
||||
|
||||
let objects = self.objectsInAllSections()
|
||||
guard objects.indices.contains(index) else {
|
||||
if self.isSectioned {
|
||||
|
||||
let fetchedObjects = self.fetchedResultsController.fetchedObjects!
|
||||
if index < fetchedObjects.count && index >= 0 {
|
||||
|
||||
return T.cs_fromRaw(object: fetchedObjects[index])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return objects[index]
|
||||
return self[safeSectionIndex: 0, safeItemIndex: index]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +139,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
|
||||
return nil
|
||||
}
|
||||
return section.objects?[itemIndex] as? T
|
||||
return T.cs_fromRaw(object: section.objects![itemIndex] as! NSManagedObject)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,7 +154,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return self.fetchedResultsController.object(at: indexPath) as! T
|
||||
return T.cs_fromRaw(object: self.fetchedResultsController.object(at: indexPath))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,42 +202,6 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
return self.numberOfObjectsInSection(safeSectionIndex: section)! > 0
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in all sections
|
||||
|
||||
- returns: all objects in all sections
|
||||
*/
|
||||
public func objectsInAllSections() -> [T] {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return (self.fetchedResultsController.dynamicCast() as NSFetchedResultsController<T>).fetchedObjects ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will raise an exception.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(_ section: Int) -> [T] {
|
||||
|
||||
return (self.sectionInfoAtIndex(section).objects as! [T]?) ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section, or `nil` if out of bounds.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [T]? {
|
||||
|
||||
return self.sectionInfoAtIndex(safeSectionIndex: section)?.objects as! [T]?
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of sections
|
||||
|
||||
@@ -371,7 +346,11 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return (self.fetchedResultsController.dynamicCast() as NSFetchedResultsController<T>).fetchedObjects?.index(of: object)
|
||||
if self.isSectioned {
|
||||
|
||||
return self.fetchedResultsController.fetchedObjects?.index(of: object.cs_toRaw())
|
||||
}
|
||||
return self.fetchedResultsController.indexPath(forObject: object.cs_toRaw())?[1]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +365,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return self.fetchedResultsController.indexPath(forObject: object)
|
||||
return self.fetchedResultsController.indexPath(forObject: object.cs_toRaw())
|
||||
}
|
||||
|
||||
|
||||
@@ -596,22 +575,22 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == <T: NSManagedObject>(lhs: ListMonitor<T>, rhs: ListMonitor<T>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
public static func == <T: NSManagedObject, U: NSManagedObject>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
public static func == (lhs: ListMonitor<T>, rhs: ListMonitor<T>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= <T: NSManagedObject>(lhs: ListMonitor<T>, rhs: ListMonitor<T>) -> Bool {
|
||||
public static func == <T: DynamicObject, U: DynamicObject>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= <T: NSManagedObject, U: NSManagedObject>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
public static func ~= (lhs: ListMonitor<T>, rhs: ListMonitor<T>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= <T: DynamicObject, U: DynamicObject>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -675,16 +654,6 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func downcast() -> ListMonitor<NSManagedObject> {
|
||||
|
||||
@inline(__always)
|
||||
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||
|
||||
return unsafeBitCast(x, to: type)
|
||||
}
|
||||
return noWarnUnsafeBitCast(self, to: ListMonitor<NSManagedObject>.self)
|
||||
}
|
||||
|
||||
internal func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<T>) -> Void) {
|
||||
|
||||
cs_setAssociatedRetainedObject(
|
||||
@@ -1001,6 +970,8 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
fileprivate let taskGroup = DispatchGroup()
|
||||
fileprivate let sectionIndexTransformer: (_ sectionName: KeyPath?) -> String?
|
||||
|
||||
private let isSectioned: Bool
|
||||
|
||||
private var willChangeListKey: Void?
|
||||
private var didChangeListKey: Void?
|
||||
private var willRefetchListKey: Void?
|
||||
@@ -1014,7 +985,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
private var didInsertSectionKey: Void?
|
||||
private var didDeleteSectionKey: Void?
|
||||
|
||||
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate<T>
|
||||
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
|
||||
private var observerForWillChangePersistentStore: NotificationObserver!
|
||||
private var observerForDidChangePersistentStore: NotificationObserver!
|
||||
private let transactionQueue: DispatchQueue
|
||||
@@ -1043,6 +1014,8 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
|
||||
private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<T>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<T>) -> Void)?) {
|
||||
|
||||
self.isSectioned = (sectionBy != nil)
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .managedObjectResultType
|
||||
@@ -1058,7 +1031,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
applyFetchClauses: applyFetchClauses
|
||||
)
|
||||
|
||||
let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate<T>()
|
||||
let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
|
||||
|
||||
self.fetchedResultsController = fetchedResultsController
|
||||
self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
|
||||
@@ -1150,9 +1123,99 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListMonitor where T: NSManagedObject
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension ListMonitor where T: NSManagedObject {
|
||||
|
||||
/**
|
||||
Returns all objects in all sections
|
||||
|
||||
- returns: all objects in all sections
|
||||
*/
|
||||
public func objectsInAllSections() -> [T] {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return (self.fetchedResultsController.dynamicCast() as NSFetchedResultsController<T>).fetchedObjects ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will raise an exception.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(_ section: Int) -> [T] {
|
||||
|
||||
return (self.sectionInfoAtIndex(section).objects as! [T]?) ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section, or `nil` if out of bounds.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [T]? {
|
||||
|
||||
return self.sectionInfoAtIndex(safeSectionIndex: section)?.objects as! [T]?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListMonitor where T: CoreStoreObject
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension ListMonitor where T: CoreStoreObject {
|
||||
|
||||
/**
|
||||
Returns all objects in all sections
|
||||
|
||||
- returns: all objects in all sections
|
||||
*/
|
||||
public func objectsInAllSections() -> [T] {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return (self.fetchedResultsController.fetchedObjects ?? [])
|
||||
.map(T.cs_fromRaw)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will raise an exception.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(_ section: Int) -> [T] {
|
||||
|
||||
return (self.sectionInfoAtIndex(section).objects ?? [])
|
||||
.map({ T.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section, or `nil` if out of bounds.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [T]? {
|
||||
|
||||
return (self.sectionInfoAtIndex(safeSectionIndex: section)?.objects)?
|
||||
.map({ T.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListMonitor: FetchedResultsControllerHandler
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension ListMonitor: FetchedResultsControllerHandler {
|
||||
|
||||
// MARK: FetchedResultsControllerHandler
|
||||
@@ -1259,7 +1322,8 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
||||
|
||||
|
||||
// MARK: - Notification Keys
|
||||
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
fileprivate extension Notification.Name {
|
||||
|
||||
fileprivate static let listMonitorWillChangeList = Notification.Name(rawValue: "listMonitorWillChangeList")
|
||||
@@ -1273,5 +1337,3 @@ fileprivate extension Notification.Name {
|
||||
fileprivate static let listMonitorDidInsertSection = Notification.Name(rawValue: "listMonitorDidInsertSection")
|
||||
fileprivate static let listMonitorDidDeleteSection = Notification.Name(rawValue: "listMonitorDidDeleteSection")
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ListObserver
|
||||
|
||||
/**
|
||||
@@ -41,12 +39,13 @@ import CoreData
|
||||
monitor.addObserver(self)
|
||||
```
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public protocol ListObserver: class {
|
||||
|
||||
/**
|
||||
The `NSManagedObject` type for the observed list
|
||||
*/
|
||||
associatedtype ListEntityType: NSManagedObject
|
||||
associatedtype ListEntityType: DynamicObject
|
||||
|
||||
/**
|
||||
Handles processing just before a change to the observed list occurs. (Optional)
|
||||
@@ -85,6 +84,7 @@ public protocol ListObserver: class {
|
||||
|
||||
// MARK: - ListObserver (Default Implementations)
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension ListObserver {
|
||||
|
||||
public func listMonitorWillChange(_ monitor: ListMonitor<ListEntityType>) { }
|
||||
@@ -109,6 +109,7 @@ public extension ListObserver {
|
||||
monitor.addObserver(self)
|
||||
```
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public protocol ListObjectObserver: ListObserver {
|
||||
|
||||
/**
|
||||
@@ -156,6 +157,7 @@ public protocol ListObjectObserver: ListObserver {
|
||||
|
||||
// MARK: - ListObjectObserver (Default Implementations)
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension ListObjectObserver {
|
||||
|
||||
public func listMonitor(_ monitor: ListMonitor<ListEntityType>, didInsertObject object: ListEntityType, toIndexPath indexPath: IndexPath) { }
|
||||
@@ -181,6 +183,7 @@ public extension ListObjectObserver {
|
||||
monitor.addObserver(self)
|
||||
```
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public protocol ListSectionObserver: ListObjectObserver {
|
||||
|
||||
/**
|
||||
@@ -207,11 +210,10 @@ public protocol ListSectionObserver: ListObjectObserver {
|
||||
|
||||
// MARK: - ListSectionObserver (Default Implementations)
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension ListSectionObserver {
|
||||
|
||||
public func listMonitor(_ monitor: ListMonitor<ListEntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { }
|
||||
|
||||
public func listMonitor(_ monitor: ListMonitor<ListEntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ObjectMonitor
|
||||
|
||||
/**
|
||||
@@ -41,14 +39,18 @@ import CoreData
|
||||
|
||||
Observers registered via `addObserver(_:)` are not retained. `ObjectMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
|
||||
*/
|
||||
public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
@available(OSX 10.12, *)
|
||||
public final class ObjectMonitor<EntityType: DynamicObject>: Equatable {
|
||||
|
||||
/**
|
||||
Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
|
||||
*/
|
||||
public var object: EntityType? {
|
||||
|
||||
return self.fetchedResultsController.fetchedObjects?.first as? EntityType
|
||||
return self.fetchedResultsController
|
||||
.fetchedObjects?
|
||||
.first
|
||||
.flatMap({ EntityType.cs_fromRaw(object: $0) })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +58,7 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
*/
|
||||
public var isObjectDeleted: Bool {
|
||||
|
||||
return self.object?.managedObjectContext == nil
|
||||
return self.object?.cs_toRaw().managedObjectContext == nil
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,22 +107,22 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == <T: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<T>) -> Bool {
|
||||
public static func == <T: DynamicObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<T>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
public static func == <T: NSManagedObject, U: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
public static func == <T: DynamicObject, U: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= <T: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<T>) -> Bool {
|
||||
public static func ~= <T: DynamicObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<T>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
public static func ~= <T: NSManagedObject, U: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
public static func ~= <T: DynamicObject, U: DynamicObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -190,7 +192,7 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
}
|
||||
|
||||
let previousCommitedAttributes = self.lastCommittedAttributes
|
||||
let currentCommitedAttributes = object.committedValues(forKeys: nil) as! [String: NSObject]
|
||||
let currentCommitedAttributes = object.cs_toRaw().committedValues(forKeys: nil) as! [String: NSObject]
|
||||
|
||||
var changedKeys = Set<String>()
|
||||
for key in currentCommitedAttributes.keys {
|
||||
@@ -220,16 +222,6 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
cs_setAssociatedRetainedObject(nilValue, forKey: &self.didUpdateObjectKey, inObject: observer)
|
||||
}
|
||||
|
||||
internal func downcast() -> ObjectMonitor<NSManagedObject> {
|
||||
|
||||
@inline(__always)
|
||||
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||
|
||||
return unsafeBitCast(x, to: type)
|
||||
}
|
||||
return noWarnUnsafeBitCast(self, to: ObjectMonitor<NSManagedObject>.self)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.fetchedResultsControllerDelegate.fetchedResultsController = nil
|
||||
@@ -239,7 +231,7 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
// MARK: Private
|
||||
|
||||
private let fetchedResultsController: CoreStoreFetchedResultsController
|
||||
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate<EntityType>
|
||||
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
|
||||
private var lastCommittedAttributes = [String: NSObject]()
|
||||
|
||||
private var willChangeObjectKey: Void?
|
||||
@@ -248,22 +240,24 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
|
||||
private init(context: NSManagedObjectContext, object: EntityType) {
|
||||
|
||||
let rawObject = object.cs_toRaw()
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
fetchRequest.entity = object.entity
|
||||
fetchRequest.entity = rawObject.entity
|
||||
fetchRequest.fetchLimit = 0
|
||||
fetchRequest.resultType = .managedObjectResultType
|
||||
fetchRequest.sortDescriptors = []
|
||||
fetchRequest.includesPendingChanges = false
|
||||
fetchRequest.shouldRefreshRefetchedObjects = true
|
||||
|
||||
let objectID = object.objectID
|
||||
let objectID = rawObject.objectID
|
||||
let fetchedResultsController = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: fetchRequest.dynamicCast(),
|
||||
from: nil as From<EntityType>?,
|
||||
applyFetchClauses: Where("SELF", isEqualTo: objectID).applyToFetchRequest
|
||||
)
|
||||
|
||||
let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate<EntityType>()
|
||||
let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
|
||||
|
||||
self.fetchedResultsController = fetchedResultsController
|
||||
self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
|
||||
@@ -272,7 +266,7 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController
|
||||
try! fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
|
||||
self.lastCommittedAttributes = (self.object?.committedValues(forKeys: nil) as? [String: NSObject]) ?? [:]
|
||||
self.lastCommittedAttributes = (self.object?.cs_toRaw().committedValues(forKeys: nil) as? [String: NSObject]) ?? [:]
|
||||
}
|
||||
|
||||
private func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor<EntityType>) -> Void) {
|
||||
@@ -281,7 +275,7 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
NotificationObserver(
|
||||
notificationName: name,
|
||||
object: self,
|
||||
closure: { [weak self] (note) -> Void in
|
||||
closure: { [weak self] _ in
|
||||
|
||||
guard let `self` = self else {
|
||||
|
||||
@@ -301,15 +295,15 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
NotificationObserver(
|
||||
notificationName: name,
|
||||
object: self,
|
||||
closure: { [weak self] (note) -> Void in
|
||||
closure: { [weak self] (note) in
|
||||
|
||||
guard let `self` = self,
|
||||
let userInfo = note.userInfo,
|
||||
let object = userInfo[String(describing: NSManagedObject.self)] as? EntityType else {
|
||||
let object = userInfo[String(describing: NSManagedObject.self)] as! NSManagedObject? else {
|
||||
|
||||
return
|
||||
}
|
||||
callback(self, object)
|
||||
callback(self, EntityType.cs_fromRaw(object: object))
|
||||
}
|
||||
),
|
||||
forKey: notificationKey,
|
||||
@@ -321,6 +315,7 @@ public final class ObjectMonitor<EntityType: NSManagedObject>: Equatable {
|
||||
|
||||
// MARK: - ObjectMonitor: FetchedResultsControllerHandler
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension ObjectMonitor: FetchedResultsControllerHandler {
|
||||
|
||||
// MARK: FetchedResultsControllerHandler
|
||||
@@ -370,11 +365,10 @@ extension ObjectMonitor: FetchedResultsControllerHandler {
|
||||
|
||||
// MARK: - Notification.Name
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
fileprivate extension Notification.Name {
|
||||
|
||||
fileprivate static let objectMonitorWillChangeObject = Notification.Name(rawValue: "objectMonitorWillChangeObject")
|
||||
fileprivate static let objectMonitorDidDeleteObject = Notification.Name(rawValue: "objectMonitorDidDeleteObject")
|
||||
fileprivate static let objectMonitorDidUpdateObject = Notification.Name(rawValue: "objectMonitorDidUpdateObject")
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ObjectObserver
|
||||
|
||||
/**
|
||||
@@ -38,12 +36,13 @@ import CoreData
|
||||
monitor.addObserver(self)
|
||||
```
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public protocol ObjectObserver: class {
|
||||
|
||||
/**
|
||||
The `NSManagedObject` type for the observed object
|
||||
*/
|
||||
associatedtype ObjectEntityType: NSManagedObject
|
||||
associatedtype ObjectEntityType: DynamicObject
|
||||
|
||||
/**
|
||||
Handles processing just before a change to the observed `object` occurs. (Optional)
|
||||
@@ -77,6 +76,7 @@ public protocol ObjectObserver: class {
|
||||
|
||||
// MARK: - ObjectObserver (Default Implementations)
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension ObjectObserver {
|
||||
|
||||
public func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, willUpdateObject object: ObjectEntityType) { }
|
||||
@@ -85,5 +85,3 @@ public extension ObjectObserver {
|
||||
|
||||
public func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, didDeleteObject object: ObjectEntityType) { }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - SectionBy
|
||||
|
||||
/**
|
||||
@@ -41,6 +39,7 @@ import CoreData
|
||||
)
|
||||
```
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public struct SectionBy {
|
||||
|
||||
/**
|
||||
@@ -72,5 +71,3 @@ public struct SectionBy {
|
||||
internal let sectionKeyPath: KeyPath
|
||||
internal let sectionIndexTransformer: (_ sectionName: String?) -> String?
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,10 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - UnsafeDataTransaction
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension UnsafeDataTransaction {
|
||||
|
||||
/**
|
||||
@@ -201,5 +200,3 @@ public extension UnsafeDataTransaction {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user