mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-15 21:53:39 +01:00
Revert ObjectMonitor to previous implementation
This commit is contained in:
@@ -16,13 +16,13 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
func setPalette<O: ObjectRepresentation>(_ newValue: O?) where O.ObjectType == Palette {
|
||||
|
||||
guard self.monitor?.objectID() != newValue?.objectID() else {
|
||||
guard self.monitor?.object?.objectID() != newValue?.objectID() else {
|
||||
|
||||
return
|
||||
}
|
||||
if let newValue = newValue {
|
||||
|
||||
self.monitor = newValue.asObjectMonitor(in: ColorsDemo.stack)
|
||||
self.monitor = newValue.asReadOnly(in: ColorsDemo.stack).map(ColorsDemo.stack.monitorObject(_:))
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
@@ -73,9 +73,30 @@ extension Palette {
|
||||
|
||||
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension LiveObject where ObjectType == Palette {
|
||||
|
||||
var color: UIColor {
|
||||
|
||||
return UIColor(
|
||||
hue: CGFloat(self.hue) / 360.0,
|
||||
saturation: CGFloat(self.saturation),
|
||||
brightness: CGFloat(self.brightness),
|
||||
alpha: 1.0
|
||||
)
|
||||
}
|
||||
|
||||
var colorText: String {
|
||||
|
||||
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
|
||||
}
|
||||
}
|
||||
|
||||
extension Palette {
|
||||
|
||||
func setInitialValues(in transaction: BaseDataTransaction) {
|
||||
|
||||
|
||||
self.hue .= Palette.randomHue()
|
||||
self.saturation .= Float(1.0)
|
||||
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
|
||||
|
||||
@@ -20,22 +20,6 @@ struct SwiftUIView: View {
|
||||
@ObservedObject
|
||||
var palettes: LiveList<Palette>
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
struct ColorCell: View {
|
||||
|
||||
@ObservedObject
|
||||
var palette: LiveObject<Palette>
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Color(palette.color)
|
||||
.cornerRadius(5)
|
||||
.frame(width: 30, height: 30, alignment: .leading)
|
||||
Text(palette.colorText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
@@ -124,6 +108,22 @@ struct SwiftUIView: View {
|
||||
private var needsShowAlert = false
|
||||
}
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
struct ColorCell: View {
|
||||
|
||||
@ObservedObject
|
||||
var palette: LiveObject<Palette>
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Color(palette.color)
|
||||
.cornerRadius(5)
|
||||
.frame(width: 30, height: 30, alignment: .leading)
|
||||
Text(palette.colorText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
struct DetailView: View {
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ extension DiffableDataSource {
|
||||
public typealias ObjectType = O
|
||||
|
||||
@nonobjc
|
||||
public init(collectionView: UICollectionView, dataStack: DataStack, cellProvider: @escaping (UICollectionView, IndexPath, ObjectType) -> UICollectionViewCell?, supplementaryViewProvider: @escaping (UICollectionView, String, IndexPath) -> UICollectionReusableView? = { _, _, _ in nil }) {
|
||||
public init(collectionView: UICollectionView, dataStack: DataStack, cellProvider: @escaping (UICollectionView, IndexPath, O) -> UICollectionViewCell?, supplementaryViewProvider: @escaping (UICollectionView, String, IndexPath) -> UICollectionReusableView? = { _, _, _ in nil }) {
|
||||
|
||||
self.collectionView = collectionView
|
||||
self.cellProvider = cellProvider
|
||||
@@ -77,7 +77,7 @@ extension DiffableDataSource {
|
||||
collectionView.dataSource = self
|
||||
}
|
||||
|
||||
public func apply(_ snapshot: ListSnapshot<ObjectType>, animatingDifferences: Bool = true) {
|
||||
public func apply(_ snapshot: ListSnapshot<O>, animatingDifferences: Bool = true) {
|
||||
|
||||
let diffableSnapshot = snapshot.diffableSnapshot
|
||||
// if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
|
||||
@@ -199,7 +199,7 @@ extension DiffableDataSource {
|
||||
private weak var collectionView: UICollectionView?
|
||||
|
||||
private let dataStack: DataStack
|
||||
private let cellProvider: (UICollectionView, IndexPath, ObjectType) -> UICollectionViewCell?
|
||||
private let cellProvider: (UICollectionView, IndexPath, O) -> UICollectionViewCell?
|
||||
private let supplementaryViewProvider: (UICollectionView, String, IndexPath) -> UICollectionReusableView?
|
||||
private var rawDataSource: Any!
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ extension DiffableDataSource {
|
||||
public typealias ObjectType = O
|
||||
|
||||
@nonobjc
|
||||
public init(tableView: UITableView, dataStack: DataStack, cellProvider: @escaping (UITableView, IndexPath, ObjectType) -> UITableViewCell?) {
|
||||
public init(tableView: UITableView, dataStack: DataStack, cellProvider: @escaping (UITableView, IndexPath, O) -> UITableViewCell?) {
|
||||
|
||||
self.tableView = tableView
|
||||
self.cellProvider = cellProvider
|
||||
@@ -82,7 +82,7 @@ extension DiffableDataSource {
|
||||
tableView.dataSource = self
|
||||
}
|
||||
|
||||
public func apply(_ snapshot: ListSnapshot<ObjectType>, animatingDifferences: Bool = true) {
|
||||
public func apply(_ snapshot: ListSnapshot<O>, animatingDifferences: Bool = true) {
|
||||
|
||||
let diffableSnapshot = snapshot.diffableSnapshot
|
||||
// if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
|
||||
@@ -221,7 +221,7 @@ extension DiffableDataSource {
|
||||
private weak var tableView: UITableView?
|
||||
|
||||
private let dataStack: DataStack
|
||||
private let cellProvider: (UITableView, IndexPath, ObjectType) -> UITableViewCell?
|
||||
private let cellProvider: (UITableView, IndexPath, O) -> UITableViewCell?
|
||||
private var rawDataSource: Any!
|
||||
|
||||
// @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
|
||||
@@ -88,10 +88,15 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
}
|
||||
return Self.init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asReadOnly(in dataStack: DataStack) -> O? {
|
||||
|
||||
return dataStack.unsafeContext().fetchExisting(self.id)
|
||||
}
|
||||
|
||||
public func asEditable(in transaction: BaseDataTransaction) -> O? {
|
||||
|
||||
return self.context.fetchExisting(self.id)
|
||||
return transaction.unsafeContext().fetchExisting(self.id)
|
||||
}
|
||||
|
||||
public func asSnapshot(in dataStack: DataStack) -> ObjectSnapshot<O>? {
|
||||
@@ -113,11 +118,6 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
}
|
||||
return .init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asObjectMonitor(in dataStack: DataStack) -> ObjectMonitor<O>? {
|
||||
|
||||
return .init(objectID: self.id, context: dataStack.unsafeContext())
|
||||
}
|
||||
|
||||
|
||||
// MARK: Equatable
|
||||
@@ -354,12 +354,4 @@ extension LiveObject where O: CoreStoreObject {
|
||||
|
||||
return self.snapshot[dynamicMember: member]
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<T>(dynamicMember member: KeyPath<O, T>) -> T {
|
||||
|
||||
return self.object[keyPath: member]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,17 +40,22 @@ 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.
|
||||
*/
|
||||
@available(macOS 10.12, *)
|
||||
public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equatable {
|
||||
public final class ObjectMonitor<O: DynamicObject>: Equatable {
|
||||
|
||||
/**
|
||||
The object type represented by this `ObjectMonitor`
|
||||
*/
|
||||
public typealias ObjectType = O
|
||||
|
||||
/**
|
||||
Returns the `DynamicObject` instance being observed, or `nil` if the object was already deleted.
|
||||
*/
|
||||
public var object: ObjectType? {
|
||||
public var object: O? {
|
||||
|
||||
return self.fetchedResultsController
|
||||
.fetchedObjects?
|
||||
.first
|
||||
.flatMap({ ObjectType.cs_fromRaw(object: $0) })
|
||||
.flatMap({ O.cs_fromRaw(object: $0) })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +77,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
|
||||
- parameter observer: an `ObjectObserver` to send change notifications to
|
||||
*/
|
||||
public func addObserver<U: ObjectObserver>(_ observer: U) where U.ObjectEntityType == ObjectType {
|
||||
public func addObserver<U: ObjectObserver>(_ observer: U) where U.ObjectEntityType == O {
|
||||
|
||||
self.unregisterObserver(observer)
|
||||
self.registerObserver(
|
||||
@@ -99,7 +104,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
|
||||
- parameter observer: an `ObjectObserver` to unregister notifications to
|
||||
*/
|
||||
public func removeObserver<U: ObjectObserver>(_ observer: U) where U.ObjectEntityType == ObjectType {
|
||||
public func removeObserver<U: ObjectObserver>(_ observer: U) where U.ObjectEntityType == O {
|
||||
|
||||
self.unregisterObserver(observer)
|
||||
}
|
||||
@@ -120,50 +125,9 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
public let userInfo = UserInfo()
|
||||
|
||||
|
||||
// MARK: ObjectRepresentation
|
||||
|
||||
public func objectID() -> O.ObjectID {
|
||||
|
||||
return self.id
|
||||
}
|
||||
|
||||
public func asLiveObject(in dataStack: DataStack) -> LiveObject<O>? {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
return .init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asEditable(in transaction: BaseDataTransaction) -> O? {
|
||||
|
||||
return self.context.fetchExisting(self.id)
|
||||
}
|
||||
|
||||
public func asSnapshot(in dataStack: DataStack) -> ObjectSnapshot<O>? {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
return .init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asSnapshot(in transaction: BaseDataTransaction) -> ObjectSnapshot<O>? {
|
||||
|
||||
let context = transaction.unsafeContext()
|
||||
return .init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asObjectMonitor(in dataStack: DataStack) -> ObjectMonitor<O>? {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
if self.context == context {
|
||||
|
||||
return self
|
||||
}
|
||||
return .init(objectID: self.id, context: dataStack.unsafeContext())
|
||||
}
|
||||
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == (lhs: ObjectMonitor<ObjectType>, rhs: ObjectMonitor<ObjectType>) -> Bool {
|
||||
public static func == (lhs: ObjectMonitor<O>, rhs: ObjectMonitor<O>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
@@ -173,7 +137,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= (lhs: ObjectMonitor<ObjectType>, rhs: ObjectMonitor<ObjectType>) -> Bool {
|
||||
public static func ~= (lhs: ObjectMonitor<O>, rhs: ObjectMonitor<O>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
@@ -194,7 +158,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(objectID: ObjectType.ObjectID, context: NSManagedObjectContext) {
|
||||
internal init(objectID: O.ObjectID, context: NSManagedObjectContext) {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObject>()
|
||||
fetchRequest.entity = objectID.entity
|
||||
@@ -207,8 +171,8 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
let fetchedResultsController = Internals.CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: fetchRequest,
|
||||
from: From<ObjectType>([objectID.persistentStore?.configurationName]),
|
||||
applyFetchClauses: Where<ObjectType>("SELF", isEqualTo: objectID).applyToFetchRequest
|
||||
from: From<O>([objectID.persistentStore?.configurationName]),
|
||||
applyFetchClauses: Where<O>("SELF", isEqualTo: objectID).applyToFetchRequest
|
||||
)
|
||||
|
||||
let fetchedResultsControllerDelegate = Internals.FetchedResultsControllerDelegate()
|
||||
@@ -224,7 +188,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
self.lastCommittedAttributes = (self.object?.cs_toRaw().committedValues(forKeys: nil) as? [String: NSObject]) ?? [:]
|
||||
}
|
||||
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, willChangeObject: @escaping (_ observer: U, _ monitor: ObjectMonitor<ObjectType>, _ object: ObjectType) -> Void, didDeleteObject: @escaping (_ observer: U, _ monitor: ObjectMonitor<ObjectType>, _ object: ObjectType) -> Void, didUpdateObject: @escaping (_ observer: U, _ monitor: ObjectMonitor<ObjectType>, _ object: ObjectType, _ changedPersistentKeys: Set<String>) -> Void) {
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, willChangeObject: @escaping (_ observer: U, _ monitor: ObjectMonitor<O>, _ object: O) -> Void, didDeleteObject: @escaping (_ observer: U, _ monitor: ObjectMonitor<O>, _ object: O) -> Void, didUpdateObject: @escaping (_ observer: U, _ monitor: ObjectMonitor<O>, _ object: O, _ changedPersistentKeys: Set<String>) -> Void) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -320,7 +284,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
return self.fetchedResultsController.managedObjectContext
|
||||
}
|
||||
|
||||
private func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor<ObjectType>) -> Void) {
|
||||
private func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor<O>) -> Void) {
|
||||
|
||||
Internals.setAssociatedRetainedObject(
|
||||
Internals.NotificationObserver(
|
||||
@@ -340,7 +304,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
)
|
||||
}
|
||||
|
||||
private func registerObjectNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor<ObjectType>, _ object: ObjectType) -> Void) {
|
||||
private func registerObjectNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor<O>, _ object: O) -> Void) {
|
||||
|
||||
Internals.setAssociatedRetainedObject(
|
||||
Internals.NotificationObserver(
|
||||
@@ -354,7 +318,7 @@ public final class ObjectMonitor<O: DynamicObject>: ObjectRepresentation, Equata
|
||||
|
||||
return
|
||||
}
|
||||
callback(self, ObjectType.cs_fromRaw(object: object))
|
||||
callback(self, O.cs_fromRaw(object: object))
|
||||
}
|
||||
),
|
||||
forKey: notificationKey,
|
||||
|
||||
@@ -47,9 +47,14 @@ public protocol ObjectRepresentation {
|
||||
An instance that may be observed for object changes.
|
||||
*/
|
||||
func asLiveObject(in dataStack: DataStack) -> LiveObject<ObjectType>?
|
||||
|
||||
/**
|
||||
A read-only instance in the `DataStack`.
|
||||
*/
|
||||
func asReadOnly(in dataStack: DataStack) -> ObjectType?
|
||||
|
||||
/**
|
||||
An instance that may be mutated within a transaction.
|
||||
An instance that may be mutated within a `BaseDataTransaction`.
|
||||
*/
|
||||
func asEditable(in transaction: BaseDataTransaction) -> ObjectType?
|
||||
|
||||
@@ -62,11 +67,6 @@ public protocol ObjectRepresentation {
|
||||
A thread-safe `struct` that is a full-copy of the object's properties
|
||||
*/
|
||||
func asSnapshot(in transaction: BaseDataTransaction) -> ObjectSnapshot<ObjectType>?
|
||||
|
||||
/**
|
||||
An instance that may be observed for property-specific changes.
|
||||
*/
|
||||
func asObjectMonitor(in dataStack: DataStack) -> ObjectMonitor<ObjectType>?
|
||||
}
|
||||
|
||||
extension NSManagedObject: ObjectRepresentation {}
|
||||
@@ -88,6 +88,16 @@ extension DynamicObject where Self: ObjectRepresentation {
|
||||
return .init(objectID: self.cs_id(), context: context)
|
||||
}
|
||||
|
||||
public func asReadOnly(in dataStack: DataStack) -> Self? {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
if self.cs_toRaw().managedObjectContext == context {
|
||||
|
||||
return self
|
||||
}
|
||||
return context.fetchExisting(self.cs_id())
|
||||
}
|
||||
|
||||
public func asEditable(in transaction: BaseDataTransaction) -> Self? {
|
||||
|
||||
let context = transaction.unsafeContext()
|
||||
@@ -109,10 +119,4 @@ extension DynamicObject where Self: ObjectRepresentation {
|
||||
let context = transaction.unsafeContext()
|
||||
return .init(objectID: self.cs_id(), context: context)
|
||||
}
|
||||
|
||||
public func asObjectMonitor(in dataStack: DataStack) -> ObjectMonitor<Self>? {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
return .init(objectID: self.cs_id(), context: context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,15 @@ public struct ObjectSnapshot<O: DynamicObject>: SnapshotResult, ObjectRepresenta
|
||||
let context = dataStack.unsafeContext()
|
||||
return .init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asReadOnly(in dataStack: DataStack) -> O? {
|
||||
|
||||
return dataStack.unsafeContext().fetchExisting(self.id)
|
||||
}
|
||||
|
||||
public func asEditable(in transaction: BaseDataTransaction) -> O? {
|
||||
|
||||
return self.context.fetchExisting(self.id)
|
||||
return transaction.unsafeContext().fetchExisting(self.id)
|
||||
}
|
||||
|
||||
public func asSnapshot(in dataStack: DataStack) -> ObjectSnapshot<O>? {
|
||||
@@ -81,11 +86,6 @@ public struct ObjectSnapshot<O: DynamicObject>: SnapshotResult, ObjectRepresenta
|
||||
}
|
||||
return .init(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asObjectMonitor(in dataStack: DataStack) -> ObjectMonitor<O>? {
|
||||
|
||||
return .init(objectID: self.id, context: dataStack.unsafeContext())
|
||||
}
|
||||
|
||||
|
||||
// MARK: Equatable
|
||||
@@ -112,7 +112,7 @@ public struct ObjectSnapshot<O: DynamicObject>: SnapshotResult, ObjectRepresenta
|
||||
|
||||
self.id = objectID
|
||||
self.context = context
|
||||
self.values = O.cs_snapshotDictionary(id: id, context: context) as NSDictionary
|
||||
self.values = O.cs_snapshotDictionary(id: objectID, context: context) as NSDictionary
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user