diff --git a/CoreStoreDemo/CoreStoreDemo/Info.plist b/CoreStoreDemo/CoreStoreDemo/Info.plist
index c99470e..3f0a53f 100644
--- a/CoreStoreDemo/CoreStoreDemo/Info.plist
+++ b/CoreStoreDemo/CoreStoreDemo/Info.plist
@@ -51,6 +51,6 @@
UIViewControllerBasedStatusBarAppearance
UIUserInterfaceStyle
- light
+ Light
diff --git a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift
index fdf851e..ccad57d 100644
--- a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift
+++ b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift
@@ -39,7 +39,7 @@ struct SwiftUIView: View {
var body: some View {
NavigationView {
List {
- ForEach(palettes.sections, id: \.self) { (sectionID) in
+ ForEach(palettes.sectionIdentifiers, id: \.self) { (sectionID) in
Section(header: Text(sectionID)) {
ForEach(self.palettes[section: sectionID], id: \.self) { palette in
NavigationLink(
@@ -118,7 +118,6 @@ struct SwiftUIView: View {
self.needsShowAlert = true
}
}
- .colorScheme(.dark)
}
@State
diff --git a/Sources/DiffableDataSourceSnapshotProtocol.swift b/Sources/DiffableDataSourceSnapshotProtocol.swift
index 46872bc..34195b6 100644
--- a/Sources/DiffableDataSourceSnapshotProtocol.swift
+++ b/Sources/DiffableDataSourceSnapshotProtocol.swift
@@ -31,4 +31,32 @@ import CoreData
internal protocol DiffableDataSourceSnapshotProtocol {
+ init()
+
+ var numberOfItems: Int { get }
+ var numberOfSections: Int { get }
+ var sectionIdentifiers: [String] { get }
+ var itemIdentifiers: [NSManagedObjectID] { get }
+
+ func numberOfItems(inSection identifier: String) -> Int
+ func itemIdentifiers(inSection identifier: String) -> [NSManagedObjectID]
+ func sectionIdentifier(containingItem identifier: NSManagedObjectID) -> String?
+ func indexOfItem(_ identifier: NSManagedObjectID) -> Int?
+ func indexOfSection(_ identifier: String) -> Int?
+
+ mutating func appendItems(_ identifiers: [NSManagedObjectID], toSection sectionIdentifier: String?)
+ mutating func insertItems(_ identifiers: [NSManagedObjectID], beforeItem beforeIdentifier: NSManagedObjectID)
+ mutating func insertItems(_ identifiers: [NSManagedObjectID], afterItem afterIdentifier: NSManagedObjectID)
+ mutating func deleteItems(_ identifiers: [NSManagedObjectID])
+ mutating func deleteAllItems()
+ mutating func moveItem(_ identifier: NSManagedObjectID, beforeItem toIdentifier: NSManagedObjectID)
+ mutating func moveItem(_ identifier: NSManagedObjectID, afterItem toIdentifier: NSManagedObjectID)
+ mutating func reloadItems(_ identifiers: [NSManagedObjectID])
+ mutating func appendSections(_ identifiers: [String])
+ mutating func insertSections(_ identifiers: [String], beforeSection toIdentifier: String)
+ mutating func insertSections(_ identifiers: [String], afterSection toIdentifier: String)
+ mutating func deleteSections(_ identifiers: [String])
+ mutating func moveSection(_ identifier: String, beforeSection toIdentifier: String)
+ mutating func moveSection(_ identifier: String, afterSection toIdentifier: String)
+ mutating func reloadSections(_ identifiers: [String])
}
diff --git a/Sources/Internals.DiffableDataSourceSnapshot.swift b/Sources/Internals.DiffableDataSourceSnapshot.swift
index deb0a74..15bcc98 100644
--- a/Sources/Internals.DiffableDataSourceSnapshot.swift
+++ b/Sources/Internals.DiffableDataSourceSnapshot.swift
@@ -40,24 +40,26 @@ import AppKit
extension Internals {
-
// MARK: - DiffableDataSourceSnapshot
// Implementation based on https://github.com/ra1028/DiffableDataSources
- internal struct DiffableDataSourceSnapshot {
+ internal struct DiffableDataSourceSnapshot: DiffableDataSourceSnapshotProtocol {
// MARK: Internal
- init() {
-
- self.structure = .init()
- }
-
init(sections: [NSFetchedResultsSectionInfo]) {
self.structure = .init(sections: sections)
}
+
+ // MARK: DiffableDataSourceSnapshotProtocol
+
+ init() {
+
+ self.structure = .init()
+ }
+
var numberOfItems: Int {
return self.structure.allItemIDs.count
@@ -68,37 +70,37 @@ extension Internals {
return self.structure.allSectionIDs.count
}
- var allSectionIDs: [String] {
+ var sectionIdentifiers: [String] {
return self.structure.allSectionIDs
}
- var allItemIDs: [NSManagedObjectID] {
+ var itemIdentifiers: [NSManagedObjectID] {
return self.structure.allItemIDs
}
func numberOfItems(inSection identifier: String) -> Int {
- return self.itemIDs(inSection: identifier).count
+ return self.itemIdentifiers(inSection: identifier).count
}
- func itemIDs(inSection identifier: String) -> [NSManagedObjectID] {
+ func itemIdentifiers(inSection identifier: String) -> [NSManagedObjectID] {
return self.structure.items(in: identifier)
}
- func sectionIDs(containingItem identifier: NSManagedObjectID) -> String? {
+ func sectionIdentifier(containingItem identifier: NSManagedObjectID) -> String? {
return self.structure.section(containing: identifier)
}
- func indexOfItemID(_ identifier: NSManagedObjectID) -> Int? {
+ func indexOfItem(_ identifier: NSManagedObjectID) -> Int? {
return self.structure.allItemIDs.firstIndex(of: identifier)
}
- func indexOfSectionID(_ identifier: String) -> Int? {
+ func indexOfSection(_ identifier: String) -> Int? {
return self.structure.allSectionIDs.firstIndex(of: identifier)
}
@@ -138,9 +140,9 @@ extension Internals {
self.structure.move(itemID: identifier, after: toIdentifier)
}
- mutating func reloadItems(_ identifiers: S, nextStateTag: UUID) where S.Element == NSManagedObjectID {
+ mutating func reloadItems(_ identifiers: [NSManagedObjectID]) {
- self.structure.update(itemIDs: identifiers, nextStateTag: nextStateTag)
+ self.structure.update(itemIDs: identifiers)
}
mutating func appendSections(_ identifiers: [String]) {
@@ -173,9 +175,9 @@ extension Internals {
self.structure.move(sectionID: identifier, after: toIdentifier)
}
- mutating func reloadSections(_ identifiers: S, nextStateTag: UUID) where S.Element == String {
+ mutating func reloadSections(_ identifiers: [String]) {
- self.structure.update(sectionIDs: identifiers, nextStateTag: nextStateTag)
+ self.structure.update(sectionIDs: identifiers)
}
@@ -388,7 +390,7 @@ extension Internals {
.insert(removed, at: itemIndex)
}
- mutating func update(itemIDs: S, nextStateTag: UUID) where S.Element == NSManagedObjectID {
+ mutating func update(itemIDs: S) where S.Element == NSManagedObjectID {
let itemPositionMap = self.itemPositionMap()
for itemID in itemIDs {
@@ -464,7 +466,7 @@ extension Internals {
self.sections.insert(removed, at: sectionIndex)
}
- mutating func update(sectionIDs: S, nextStateTag: UUID) where S.Element == String {
+ mutating func update(sectionIDs: S) where S.Element == String {
for sectionID in sectionIDs {
@@ -590,4 +592,76 @@ extension Internals {
}
+// MARK: - NSDiffableDataSourceSnapshot: DiffableDataSourceSnapshotProtocol
+
+@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *)
+extension NSDiffableDataSourceSnapshot: DiffableDataSourceSnapshotProtocol where SectionIdentifierType == NSString, ItemIdentifierType == NSManagedObjectID {
+
+ internal var sectionIdentifiers: [String] {
+
+ return self.sectionIdentifiers as [NSString] as [String]
+ }
+
+ internal func numberOfItems(inSection identifier: String) -> Int {
+
+ return self.numberOfItems(inSection: identifier as NSString)
+ }
+
+ internal func itemIdentifiers(inSection identifier: String) -> [NSManagedObjectID] {
+
+ return self.itemIdentifiers(inSection: identifier as NSString)
+ }
+
+ internal func sectionIdentifier(containingItem identifier: NSManagedObjectID) -> String? {
+
+ return self.sectionIdentifier(containingItem: identifier) as NSString? as String?
+ }
+
+ internal func indexOfSection(_ identifier: String) -> Int? {
+
+ return self.indexOfSection(identifier as NSString)
+ }
+
+ internal mutating func appendItems(_ identifiers: [NSManagedObjectID], toSection sectionIdentifier: String?) {
+
+ self.appendItems(identifiers, toSection: sectionIdentifier as NSString?)
+ }
+
+ internal mutating func appendSections(_ identifiers: [String]) {
+
+ self.appendSections(identifiers as [NSString])
+ }
+
+ internal mutating func insertSections(_ identifiers: [String], beforeSection toIdentifier: String) {
+
+ self.insertSections(identifiers as [NSString], beforeSection: toIdentifier as NSString)
+ }
+
+ internal mutating func insertSections(_ identifiers: [String], afterSection toIdentifier: String) {
+
+ return self.insertSections(identifiers as [NSString], afterSection: toIdentifier as NSString)
+ }
+
+ internal mutating func deleteSections(_ identifiers: [String]) {
+
+ self.deleteSections(identifiers as [NSString])
+ }
+
+ internal mutating func moveSection(_ identifier: String, beforeSection toIdentifier: String) {
+
+ self.moveSection(identifier as NSString, beforeSection: toIdentifier as NSString)
+ }
+
+ internal mutating func moveSection(_ identifier: String, afterSection toIdentifier: String) {
+
+ self.moveSection(identifier as NSString, afterSection: toIdentifier as NSString)
+ }
+
+ internal mutating func reloadSections(_ identifiers: [String]) {
+
+ self.reloadSections(identifiers as [NSString])
+ }
+}
+
+
#endif
diff --git a/Sources/Internals.FetchedDiffableDataSourceSnapshotDelegate.swift b/Sources/Internals.FetchedDiffableDataSourceSnapshotDelegate.swift
index a49e902..5a1ad65 100644
--- a/Sources/Internals.FetchedDiffableDataSourceSnapshotDelegate.swift
+++ b/Sources/Internals.FetchedDiffableDataSourceSnapshotDelegate.swift
@@ -41,7 +41,7 @@ import AppKit
internal protocol FetchedDiffableDataSourceSnapshotHandler: AnyObject {
- func controller(_ controller: NSFetchedResultsController, didChangContentWith snapshot: Internals.DiffableDataSourceSnapshot)
+ func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: DiffableDataSourceSnapshotProtocol)
}
@@ -75,14 +75,14 @@ extension Internals {
internal func initialFetch() {
-// #if canImport(UIKit) || canImport(AppKit)
-//
-// if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
-//
-// return
-// }
-//
-// #endif
+ #if canImport(UIKit) || canImport(AppKit)
+
+ if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
+
+ return
+ }
+
+ #endif
guard let fetchedResultsController = self.fetchedResultsController else {
@@ -94,26 +94,26 @@ extension Internals {
// MARK: NSFetchedResultsControllerDelegate
-// #if canImport(UIKit) || canImport(AppKit)
-//
-// @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
-// @objc
-// dynamic func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
-//
-// self.handler?.controller(
-// controller,
-// didChangContentWith: snapshot as NSDiffableDataSourceSnapshot
-// )
-// }
-//
-// #endif
+ #if canImport(UIKit) || canImport(AppKit)
+
+ @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
+ @objc
+ dynamic func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
+
+ self.handler?.controller(
+ controller,
+ didChangeContentWith: snapshot as NSDiffableDataSourceSnapshot
+ )
+ }
+
+ #endif
@objc
dynamic func controllerDidChangeContent(_ controller: NSFetchedResultsController) {
self.handler?.controller(
controller,
- didChangContentWith: Internals.DiffableDataSourceSnapshot(
+ didChangeContentWith: Internals.DiffableDataSourceSnapshot(
sections: controller.sections ?? []
)
)
diff --git a/Sources/Internals.SharedNotificationObserver.swift b/Sources/Internals.SharedNotificationObserver.swift
index c97aa4c..e724ab5 100644
--- a/Sources/Internals.SharedNotificationObserver.swift
+++ b/Sources/Internals.SharedNotificationObserver.swift
@@ -25,32 +25,83 @@
import Foundation
-
// MARK: - Internal
extension Internals {
// MARK: - SharedNotificationObserver
- internal final class SharedNotificationObserver {
+ internal final class SharedNotificationObserver {
// MARK: Internal
- let observer: NSObjectProtocol
-
- init(notificationName: Notification.Name, object: Any?, queue: OperationQueue? = nil, closure: @escaping (_ note: Notification) -> Void) {
+ internal init(notificationName: Notification.Name, object: Any?, queue: OperationQueue? = nil, sharedValue: @escaping (_ note: Notification) -> T) {
self.observer = NotificationCenter.default.addObserver(
forName: notificationName,
object: object,
queue: queue,
- using: closure
+ using: { [weak self] (notification) in
+
+ guard let self = self else {
+
+ return
+ }
+ let value = sharedValue(notification)
+ self.notifyObservers(value)
+ }
)
}
deinit {
- NotificationCenter.default.removeObserver(self.observer)
+ self.observer.map(NotificationCenter.default.removeObserver(_:))
+ }
+
+ internal func addObserver(_ observer: U, closure: @escaping (T) -> Void) {
+
+ self.observers.setObject(Closure(closure), forKey: observer)
+ }
+
+
+ // MARK: Private
+
+ private var observer: NSObjectProtocol!
+ private let observers: NSMapTable = .weakToStrongObjects()
+
+ private func notifyObservers(_ sharedValue: T) {
+
+ guard let enumerator = self.observers.objectEnumerator() else {
+
+ return
+ }
+ for closure in enumerator {
+
+ (closure as! Closure).invoke(with: sharedValue)
+ }
+ }
+
+
+ // MARK: - Closure
+
+ fileprivate final class Closure {
+
+ // MARK: FilePrivate
+
+ fileprivate init(_ closure: @escaping (T) -> Void) {
+
+ self.closure = closure
+ }
+
+ fileprivate func invoke(with argument: T) {
+
+ self.closure(argument)
+ }
+
+
+ // MARK: Private
+
+ private let closure: (T) -> Void
}
}
}
diff --git a/Sources/ListSnapshot.swift b/Sources/ListSnapshot.swift
index 51b985d..4a03c73 100644
--- a/Sources/ListSnapshot.swift
+++ b/Sources/ListSnapshot.swift
@@ -46,7 +46,7 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public subscript(indices indices: S) -> [LiveObject] where S.Element == Index {
let context = self.context!
- let itemIDs = self.diffableSnapshot.allItemIDs
+ let itemIDs = self.diffableSnapshot.itemIdentifiers
return indices.map { position in
let itemID = itemIDs[position]
@@ -57,7 +57,7 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public subscript(section sectionID: SectionID) -> [LiveObject] {
let context = self.context!
- let itemIDs = self.diffableSnapshot.itemIDs(inSection: sectionID)
+ let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: sectionID)
return itemIDs.map {
return LiveObject(id: $0, context: context)
@@ -67,7 +67,7 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public subscript(section sectionID: SectionID, itemIndices itemIndices: S) -> [LiveObject] where S.Element == Int {
let context = self.context!
- let itemIDs = self.diffableSnapshot.itemIDs(inSection: sectionID)
+ let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: sectionID)
return itemIndices.map { position in
let itemID = itemIDs[position]
@@ -85,14 +85,14 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
return self.diffableSnapshot.numberOfSections
}
- public var sectionIDs: [SectionID] {
+ public var sectionIdentifiers: [SectionID] {
- return self.diffableSnapshot.allSectionIDs
+ return self.diffableSnapshot.sectionIdentifiers
}
public var itemIdentifiers: [ItemID] {
- return self.diffableSnapshot.allItemIDs
+ return self.diffableSnapshot.itemIdentifiers
}
public func numberOfItems(inSection identifier: SectionID) -> Int {
@@ -102,28 +102,28 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public func itemIdentifiers(inSection identifier: SectionID) -> [ItemID] {
- return self.diffableSnapshot.itemIDs(inSection: identifier)
+ return self.diffableSnapshot.itemIdentifiers(inSection: identifier)
}
public func itemIdentifiers(inSection identifier: SectionID, atIndices indices: IndexSet) -> [ItemID] {
- let itemIDs = self.diffableSnapshot.itemIDs(inSection: identifier)
+ let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: identifier)
return indices.map({ itemIDs[$0] })
}
public func sectionIdentifier(containingItem identifier: ItemID) -> SectionID? {
- return self.diffableSnapshot.sectionIDs(containingItem: identifier)
+ return self.diffableSnapshot.sectionIdentifier(containingItem: identifier)
}
public func indexOfItem(_ identifier: ItemID) -> Index? {
- return self.diffableSnapshot.indexOfItemID(identifier)
+ return self.diffableSnapshot.indexOfItem(identifier)
}
public func indexOfSection(_ identifier: SectionID) -> Int? {
- return self.diffableSnapshot.indexOfSectionID(identifier)
+ return self.diffableSnapshot.indexOfSection(identifier)
}
public mutating func appendItems(_ identifiers: [ItemID], toSection sectionIdentifier: SectionID? = nil) {
@@ -163,7 +163,7 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public mutating func reloadItems(_ identifiers: [ItemID]) {
- self.diffableSnapshot.reloadItems(identifiers, nextStateTag: .init())
+ self.diffableSnapshot.reloadItems(identifiers)
}
public mutating func appendSections(_ identifiers: [SectionID]) {
@@ -198,7 +198,7 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public mutating func reloadSections(_ identifiers: [SectionID]) {
- self.diffableSnapshot.reloadSections(identifiers, nextStateTag: .init())
+ self.diffableSnapshot.reloadSections(identifiers)
}
@@ -211,18 +211,18 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
public var startIndex: Index {
- return self.diffableSnapshot.allItemIDs.startIndex
+ return self.diffableSnapshot.itemIdentifiers.startIndex
}
public var endIndex: Index {
- return self.diffableSnapshot.allItemIDs.endIndex
+ return self.diffableSnapshot.itemIdentifiers.endIndex
}
public subscript(position: Index) -> Element {
let context = self.context!
- let itemID = self.diffableSnapshot.allItemIDs[position]
+ let itemID = self.diffableSnapshot.itemIdentifiers[position]
return LiveObject(id: itemID, context: context)
}
@@ -254,11 +254,11 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
internal init() {
- self.diffableSnapshot = .init()
+ self.diffableSnapshot = Internals.DiffableDataSourceSnapshot()
self.context = nil
}
- internal init(diffableSnapshot: Internals.DiffableDataSourceSnapshot, context: NSManagedObjectContext) {
+ internal init(diffableSnapshot: DiffableDataSourceSnapshotProtocol, context: NSManagedObjectContext) {
self.diffableSnapshot = diffableSnapshot
self.context = context
@@ -270,5 +270,5 @@ public struct ListSnapshot: SnapshotResult, RandomAccessCollec
private let id: UUID = .init()
private let context: NSManagedObjectContext?
- private var diffableSnapshot: Internals.DiffableDataSourceSnapshot
+ private var diffableSnapshot: DiffableDataSourceSnapshotProtocol
}
diff --git a/Sources/LiveList.swift b/Sources/LiveList.swift
index da455aa..35fc7c5 100644
--- a/Sources/LiveList.swift
+++ b/Sources/LiveList.swift
@@ -63,9 +63,9 @@ public final class LiveList: Hashable {
return self.snapshot.numberOfSections
}
- public var sections: [SectionID] {
+ public var sectionIdentifiers: [SectionID] {
- return self.snapshot.sectionIDs
+ return self.snapshot.sectionIdentifiers
}
public subscript(section sectionID: SectionID) -> [LiveObject] {
@@ -302,7 +302,7 @@ extension LiveList: FetchedDiffableDataSourceSnapshotHandler {
// MARK: FetchedDiffableDataSourceSnapshotHandler
- internal func controller(_ controller: NSFetchedResultsController, didChangContentWith snapshot: Internals.DiffableDataSourceSnapshot) {
+ internal func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: DiffableDataSourceSnapshotProtocol) {
self.snapshot = .init(
diffableSnapshot: snapshot,
diff --git a/Sources/LiveObject.swift b/Sources/LiveObject.swift
index 2e6c937..545c8bc 100644
--- a/Sources/LiveObject.swift
+++ b/Sources/LiveObject.swift
@@ -114,36 +114,23 @@ public final class LiveObject: Identifiable, Hashable {
self.rawObjectWillChange = nil
}
- self.observer = NotificationCenter.default.addObserver(
- forName: .NSManagedObjectContextObjectsDidChange,
- object: context,
- queue: .main,
- using: { [weak self] (notification) in
-
- guard let self = self, let userInfo = notification.userInfo else {
-
- return
- }
- let updatedObjects = (userInfo[NSUpdatedObjectsKey] as! NSSet? ?? [])
- let mergedObjects = (userInfo[NSRefreshedObjectsKey] as! NSSet? ?? [])
- guard mergedObjects.contains(where: { ($0 as! NSManagedObject).objectID == id })
- || updatedObjects.contains(where: { ($0 as! NSManagedObject).objectID == id }) else {
-
- return
- }
- self.$lazySnapshot.reset({ initializer(id, context) })
- self.willChange()
- }
- )
-
self.$lazySnapshot.initialize({ initializer(id, context) })
+
+ context.objectsDidChangeObserver(for: self).addObserver(self) { [weak self] (objectIDs) in
+
+ guard let self = self else {
+
+ return
+ }
+ self.$lazySnapshot.reset({ initializer(id, context) })
+ self.willChange()
+ }
}
// MARK: Private
private let context: NSManagedObjectContext
- private var observer: NSObjectProtocol?
@Internals.LazyNonmutating(uninitialized: ())
private var lazySnapshot: ObjectSnapshot
diff --git a/Sources/NSManagedObjectContext+CoreStore.swift b/Sources/NSManagedObjectContext+CoreStore.swift
index ffe0b9f..10524c4 100644
--- a/Sources/NSManagedObjectContext+CoreStore.swift
+++ b/Sources/NSManagedObjectContext+CoreStore.swift
@@ -89,7 +89,10 @@ extension NSManagedObjectContext {
@nonobjc
internal func liveObject(id: NSManagedObjectID) -> LiveObject {
- let cache = self.liveObjectsCache(D.self)
+ let cache: NSMapTable> = self.userInfo(for: .liveObjectsCache(D.self)) {
+
+ return .strongToWeakObjects()
+ }
return Internals.with {
if let liveObject = cache.object(forKey: id) {
@@ -103,27 +106,38 @@ extension NSManagedObjectContext {
}
@nonobjc
- private func liveObjectsCache(_ objectType: D.Type) -> NSMapTable> {
+ internal func objectsDidChangeObserver(for observer: U) -> Internals.SharedNotificationObserver> {
- let key = Internals.typeName(objectType)
- if let cache = self.userInfo[key] {
+ return self.userInfo(for: .objectsChangeObserver(U.self)) { [unowned self] in
- return cache as! NSMapTable>
+ return .init(
+ notificationName: .NSManagedObjectContextObjectsDidChange,
+ object: self,
+ queue: .main,
+ sharedValue: { (notification) -> Set in
+
+ guard let userInfo = notification.userInfo else {
+
+ return []
+ }
+ var updatedObjectIDs: Set = []
+ if let updatedObjects = userInfo[NSUpdatedObjectsKey] as? Set {
+
+ updatedObjectIDs.formUnion(updatedObjects)
+ }
+ if let mergedObjects = userInfo[NSRefreshedObjectsKey] as? Set {
+
+ updatedObjectIDs.formUnion(mergedObjects)
+ }
+ return updatedObjectIDs
+ }
+ )
}
- let cache = NSMapTable>.strongToWeakObjects()
- self.userInfo[key] = cache
- return cache
}
// MARK: Private
- private struct PropertyKeys {
-
- static var observerForWillSaveNotification: Void?
- static var shouldCascadeSavesToParent: Void?
- }
-
@nonobjc
private var observerForWillSaveNotification: Internals.NotificationObserver? {
@@ -143,5 +157,47 @@ extension NSManagedObjectContext {
)
}
}
+
+ private func userInfo(for key: UserInfoKeys, initialize: @escaping () -> T) -> T {
+
+ let keyString = key.keyString
+ if let value = self.userInfo[keyString] {
+
+ return value as! T
+ }
+ let value = initialize()
+ self.userInfo[keyString] = value
+ return value
+ }
+
+
+ // MARK: - PropertyKeys
+
+ private struct PropertyKeys {
+
+ static var observerForWillSaveNotification: Void?
+ static var shouldCascadeSavesToParent: Void?
+ }
+
+
+ // MARK: - UserInfoKeys
+
+ private enum UserInfoKeys {
+
+ case liveObjectsCache(DynamicObject.Type)
+ case objectsChangeObserver(AnyObject.Type)
+
+ var keyString: String {
+
+ switch self {
+
+ case .liveObjectsCache(let objectType):
+ return "CoreStore.liveObjectsCache(\(Internals.typeName(objectType)))"
+
+ case .objectsChangeObserver:
+ return "CoreStore.objectsChangeObserver"
+ }
+ }
+ }
}