mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-09 06:40:08 +01:00
Renamed LiveList to ListPublisher and LiveObject to ObjectPublisher. WIP: docs
This commit is contained in:
@@ -70,10 +70,10 @@
|
||||
82BA18D81C4BBD7100A0916E /* Internals.WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* Internals.WeakObject.swift */; };
|
||||
82BA18DC1C4BBD9C00A0916E /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
|
||||
82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
|
||||
B501322A2344ECB500FC238B /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* LiveList.swift */; };
|
||||
B501322B2346A9AE00FC238B /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* LiveList.swift */; };
|
||||
B501322D2346A9B000FC238B /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* LiveList.swift */; };
|
||||
B501322E2346A9B100FC238B /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* LiveList.swift */; };
|
||||
B501322A2344ECB500FC238B /* ListPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* ListPublisher.swift */; };
|
||||
B501322B2346A9AE00FC238B /* ListPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* ListPublisher.swift */; };
|
||||
B501322D2346A9B000FC238B /* ListPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* ListPublisher.swift */; };
|
||||
B501322E2346A9B100FC238B /* ListPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132292344ECB500FC238B /* ListPublisher.swift */; };
|
||||
B50132302346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501322F2346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift */; };
|
||||
B50132312346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501322F2346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift */; };
|
||||
B50132322346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501322F2346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift */; };
|
||||
@@ -600,10 +600,10 @@
|
||||
B5BF7FBD234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FBB234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift */; };
|
||||
B5BF7FBE234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FBB234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift */; };
|
||||
B5BF7FBF234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FBB234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift */; };
|
||||
B5BF7FC1234D7B2E0070E741 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* LiveObject.swift */; };
|
||||
B5BF7FC2234D7B2E0070E741 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* LiveObject.swift */; };
|
||||
B5BF7FC3234D7B2E0070E741 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* LiveObject.swift */; };
|
||||
B5BF7FC4234D7B2E0070E741 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* LiveObject.swift */; };
|
||||
B5BF7FC1234D7B2E0070E741 /* ObjectPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* ObjectPublisher.swift */; };
|
||||
B5BF7FC2234D7B2E0070E741 /* ObjectPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* ObjectPublisher.swift */; };
|
||||
B5BF7FC3234D7B2E0070E741 /* ObjectPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* ObjectPublisher.swift */; };
|
||||
B5BF7FC4234D7B2E0070E741 /* ObjectPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC0234D7B2E0070E741 /* ObjectPublisher.swift */; };
|
||||
B5BF7FC6234D7E460070E741 /* ObjectSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC5234D7E460070E741 /* ObjectSnapshot.swift */; };
|
||||
B5BF7FC7234D7E460070E741 /* ObjectSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC5234D7E460070E741 /* ObjectSnapshot.swift */; };
|
||||
B5BF7FC8234D7E460070E741 /* ObjectSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FC5234D7E460070E741 /* ObjectSnapshot.swift */; };
|
||||
@@ -668,9 +668,9 @@
|
||||
B5D8CA772346EAEE0055D7D1 /* DataStack+DataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA752346E7590055D7D1 /* DataStack+DataSources.swift */; };
|
||||
B5D8CA782346EAEF0055D7D1 /* DataStack+DataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA752346E7590055D7D1 /* DataStack+DataSources.swift */; };
|
||||
B5D8CA792346EAEF0055D7D1 /* DataStack+DataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA752346E7590055D7D1 /* DataStack+DataSources.swift */; };
|
||||
B5D8CA7C2346EC5F0055D7D1 /* LiveListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* LiveListTests.swift */; };
|
||||
B5D8CA7D2346EC610055D7D1 /* LiveListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* LiveListTests.swift */; };
|
||||
B5D8CA7E2346EC610055D7D1 /* LiveListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* LiveListTests.swift */; };
|
||||
B5D8CA7C2346EC5F0055D7D1 /* ListPublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* ListPublisherTests.swift */; };
|
||||
B5D8CA7D2346EC610055D7D1 /* ListPublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* ListPublisherTests.swift */; };
|
||||
B5D8CA7E2346EC610055D7D1 /* ListPublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* ListPublisherTests.swift */; };
|
||||
B5DAFB482203D9F8003FCCD0 /* Where.Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DAFB472203D9F8003FCCD0 /* Where.Expression.swift */; };
|
||||
B5DAFB4A2203E01D003FCCD0 /* KeyPathGenericBindings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DAFB492203E01D003FCCD0 /* KeyPathGenericBindings.swift */; };
|
||||
B5DBE2CD1C9914A900B5CEFA /* CSCoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBE2CC1C9914A900B5CEFA /* CSCoreStore.swift */; };
|
||||
@@ -722,10 +722,6 @@
|
||||
B5E2222C1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; };
|
||||
B5E2222D1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; };
|
||||
B5E2222E1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; };
|
||||
B5E294DD2349F8E7003E5956 /* SnapshotResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */; };
|
||||
B5E294DE2349F8E7003E5956 /* SnapshotResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */; };
|
||||
B5E294DF2349F8E7003E5956 /* SnapshotResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */; };
|
||||
B5E294E02349F8E7003E5956 /* SnapshotResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */; };
|
||||
B5E41EC01EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E41EBF1EA9BB37006240F0 /* DynamicSchema+Convenience.swift */; };
|
||||
B5E41EC11EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E41EBF1EA9BB37006240F0 /* DynamicSchema+Convenience.swift */; };
|
||||
B5E41EC21EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E41EBF1EA9BB37006240F0 /* DynamicSchema+Convenience.swift */; };
|
||||
@@ -818,10 +814,6 @@
|
||||
B5ECDC331CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDC2E1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift */; };
|
||||
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */; };
|
||||
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */; };
|
||||
B5F335582348D75D00FD649F /* LiveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F335572348D75D00FD649F /* LiveResult.swift */; };
|
||||
B5F335592348D76300FD649F /* LiveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F335572348D75D00FD649F /* LiveResult.swift */; };
|
||||
B5F3355A2348D76500FD649F /* LiveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F335572348D75D00FD649F /* LiveResult.swift */; };
|
||||
B5F3355B2348D76500FD649F /* LiveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F335572348D75D00FD649F /* LiveResult.swift */; };
|
||||
B5F8496C234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; };
|
||||
B5F8496D234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; };
|
||||
B5F8496E234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; };
|
||||
@@ -884,7 +876,7 @@
|
||||
82BA18DE1C4BBE2600A0916E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
|
||||
82BA18E01C4BBE2C00A0916E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.1.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; };
|
||||
B500810F2290CDF800F4CEA5 /* bitrise.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = bitrise.yml; sourceTree = SOURCE_ROOT; };
|
||||
B50132292344ECB500FC238B /* LiveList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveList.swift; sourceTree = "<group>"; };
|
||||
B50132292344ECB500FC238B /* ListPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListPublisher.swift; sourceTree = "<group>"; };
|
||||
B501322F2346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.FetchedDiffableDataSourceSnapshotDelegate.swift; sourceTree = "<group>"; };
|
||||
B501323623477F9300FC238B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; };
|
||||
B501323823477FAC00FC238B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
@@ -1021,7 +1013,7 @@
|
||||
B5BF7FB1234C97910070E741 /* DiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableDataSource.swift; sourceTree = "<group>"; };
|
||||
B5BF7FB6234C97CE0070E741 /* DiffableDataSource.TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableDataSource.TableView.swift; sourceTree = "<group>"; };
|
||||
B5BF7FBB234C99190070E741 /* Internals.DiffableDataUIDispatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.DiffableDataUIDispatcher.swift; sourceTree = "<group>"; };
|
||||
B5BF7FC0234D7B2E0070E741 /* LiveObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveObject.swift; sourceTree = "<group>"; };
|
||||
B5BF7FC0234D7B2E0070E741 /* ObjectPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectPublisher.swift; sourceTree = "<group>"; };
|
||||
B5BF7FC5234D7E460070E741 /* ObjectSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectSnapshot.swift; sourceTree = "<group>"; };
|
||||
B5BF7FCA234D80910070E741 /* Internals.LazyNonmutating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.LazyNonmutating.swift; sourceTree = "<group>"; };
|
||||
B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; };
|
||||
@@ -1042,7 +1034,7 @@
|
||||
B5D39A0119FD00C9000E91BB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
B5D7A5B51CA3BF8F005C752B /* CSInto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSInto.swift; sourceTree = "<group>"; };
|
||||
B5D8CA752346E7590055D7D1 /* DataStack+DataSources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataStack+DataSources.swift"; sourceTree = "<group>"; };
|
||||
B5D8CA7A2346EC550055D7D1 /* LiveListTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveListTests.swift; sourceTree = "<group>"; };
|
||||
B5D8CA7A2346EC550055D7D1 /* ListPublisherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListPublisherTests.swift; sourceTree = "<group>"; };
|
||||
B5D9C8F61B160ED200E64F0E /* CoreStore.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = CoreStore.podspec; sourceTree = SOURCE_ROOT; };
|
||||
B5DAFB472203D9F8003FCCD0 /* Where.Expression.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Where.Expression.swift; sourceTree = "<group>"; };
|
||||
B5DAFB492203E01D003FCCD0 /* KeyPathGenericBindings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPathGenericBindings.swift; sourceTree = "<group>"; };
|
||||
@@ -1062,7 +1054,6 @@
|
||||
B5E1B5A71CAA49E2007FD580 /* CSDataStack+Migrating.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSDataStack+Migrating.swift"; sourceTree = "<group>"; };
|
||||
B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSynchronousDataTransaction.swift; sourceTree = "<group>"; };
|
||||
B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSUnsafeDataTransaction.swift; sourceTree = "<group>"; };
|
||||
B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotResult.swift; sourceTree = "<group>"; };
|
||||
B5E41EBF1EA9BB37006240F0 /* DynamicSchema+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DynamicSchema+Convenience.swift"; sourceTree = "<group>"; };
|
||||
B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BaseDataTransaction+Importing.swift"; sourceTree = "<group>"; };
|
||||
B5E84ED81AFF82360064E85B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
|
||||
@@ -1115,7 +1106,6 @@
|
||||
B5ECDC2E1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Transaction.swift"; sourceTree = "<group>"; };
|
||||
B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableObject.swift; sourceTree = "<group>"; };
|
||||
B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableUniqueObject.swift; sourceTree = "<group>"; };
|
||||
B5F335572348D75D00FD649F /* LiveResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveResult.swift; sourceTree = "<group>"; };
|
||||
B5F8496B234898240029D57B /* ListSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSnapshot.swift; sourceTree = "<group>"; };
|
||||
B5F849702348A6690029D57B /* EnvironmentValues+DataSources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+DataSources.swift"; sourceTree = "<group>"; };
|
||||
B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Progress+Convenience.swift"; sourceTree = "<group>"; };
|
||||
@@ -1264,7 +1254,7 @@
|
||||
B5220E0B1D0D0D19009BC71E /* ImportTests.swift */,
|
||||
B525576B1CFAF18F00E51965 /* IntoTests.swift */,
|
||||
B5220E0F1D0DA6AB009BC71E /* ListObserverTests.swift */,
|
||||
B5D8CA7A2346EC550055D7D1 /* LiveListTests.swift */,
|
||||
B5D8CA7A2346EC550055D7D1 /* ListPublisherTests.swift */,
|
||||
B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */,
|
||||
B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */,
|
||||
B52557771D02826E00E51965 /* OrderByTests.swift */,
|
||||
@@ -1597,15 +1587,13 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5F849702348A6690029D57B /* EnvironmentValues+DataSources.swift */,
|
||||
B50132292344ECB500FC238B /* LiveList.swift */,
|
||||
B5BF7FC0234D7B2E0070E741 /* LiveObject.swift */,
|
||||
B50132292344ECB500FC238B /* ListPublisher.swift */,
|
||||
B5F8496B234898240029D57B /* ListSnapshot.swift */,
|
||||
B5BF7FC0234D7B2E0070E741 /* ObjectPublisher.swift */,
|
||||
B5BF7FC5234D7E460070E741 /* ObjectSnapshot.swift */,
|
||||
B55BB4D3235012AE00C33E34 /* ObjectRepresentation.swift */,
|
||||
B50EE14123473C92009B8C47 /* CoreStoreObject+DataSources.swift */,
|
||||
B5D8CA752346E7590055D7D1 /* DataStack+DataSources.swift */,
|
||||
B5F335572348D75D00FD649F /* LiveResult.swift */,
|
||||
B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */,
|
||||
B5BF7FB1234C97910070E741 /* DiffableDataSource.swift */,
|
||||
B5BF7FB6234C97CE0070E741 /* DiffableDataSource.TableView.swift */,
|
||||
B5635D132356C39500B80E6B /* DiffableDataSource.CollectionView.swift */,
|
||||
@@ -2119,7 +2107,6 @@
|
||||
B5D339E21E948C3600C880DE /* Value.swift in Sources */,
|
||||
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */,
|
||||
B53FBA0B1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
|
||||
B5E294DD2349F8E7003E5956 /* SnapshotResult.swift in Sources */,
|
||||
B5E84F141AFF847B0064E85B /* DataStack+Querying.swift in Sources */,
|
||||
B5D7A5B61CA3BF8F005C752B /* CSInto.swift in Sources */,
|
||||
B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */,
|
||||
@@ -2133,7 +2120,7 @@
|
||||
B51B5C2D22D43E38009FA3BA /* KeyPath+KeyPaths.swift in Sources */,
|
||||
B50564D32350CC3100482308 /* PropertyProtocol.swift in Sources */,
|
||||
B5D8CA762346E7590055D7D1 /* DataStack+DataSources.swift in Sources */,
|
||||
B5BF7FC1234D7B2E0070E741 /* LiveObject.swift in Sources */,
|
||||
B5BF7FC1234D7B2E0070E741 /* ObjectPublisher.swift in Sources */,
|
||||
B5E1B5A81CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B50132302346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift in Sources */,
|
||||
B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
@@ -2148,7 +2135,6 @@
|
||||
B50E175C2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
|
||||
B5ECDC291CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
|
||||
B56923F01EB827F6007C4DC9 /* XcodeSchemaMappingProvider.swift in Sources */,
|
||||
B5F335582348D75D00FD649F /* LiveResult.swift in Sources */,
|
||||
B5E84F121AFF847B0064E85B /* OrderBy.swift in Sources */,
|
||||
B546F9581C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */,
|
||||
B5635D142356C39500B80E6B /* DiffableDataSource.CollectionView.swift in Sources */,
|
||||
@@ -2269,7 +2255,7 @@
|
||||
B5ECDC0B1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
|
||||
B5E84F151AFF847B0064E85B /* CoreStore+Querying.swift in Sources */,
|
||||
B5E84F241AFF84860064E85B /* ListObserver.swift in Sources */,
|
||||
B501322A2344ECB500FC238B /* LiveList.swift in Sources */,
|
||||
B501322A2344ECB500FC238B /* ListPublisher.swift in Sources */,
|
||||
B5F8496C234898240029D57B /* ListSnapshot.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -2283,7 +2269,7 @@
|
||||
B5220E101D0DA6AB009BC71E /* ListObserverTests.swift in Sources */,
|
||||
B5519A401CA1B17B002BEF78 /* ErrorTests.swift in Sources */,
|
||||
B525577C1D0291FE00E51965 /* GroupByTests.swift in Sources */,
|
||||
B5D8CA7C2346EC5F0055D7D1 /* LiveListTests.swift in Sources */,
|
||||
B5D8CA7C2346EC5F0055D7D1 /* ListPublisherTests.swift in Sources */,
|
||||
B52557741D02791400E51965 /* WhereTests.swift in Sources */,
|
||||
B5DC47C61C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
|
||||
B525576C1CFAF18F00E51965 /* IntoTests.swift in Sources */,
|
||||
@@ -2329,7 +2315,7 @@
|
||||
82BA18CE1C4BBD7100A0916E /* Internals.FetchedResultsControllerDelegate.swift in Sources */,
|
||||
B56923FB1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
|
||||
B55514EB1EED8BF900BAB888 /* From+Querying.swift in Sources */,
|
||||
B5BF7FC2234D7B2E0070E741 /* LiveObject.swift in Sources */,
|
||||
B5BF7FC2234D7B2E0070E741 /* ObjectPublisher.swift in Sources */,
|
||||
B596BBBC1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
B55BB4D5235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
@@ -2352,7 +2338,6 @@
|
||||
82BA18BD1C4BBD4A00A0916E /* GroupBy.swift in Sources */,
|
||||
B5ECDC1F1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
|
||||
B5BF7FCC234D80910070E741 /* Internals.LazyNonmutating.swift in Sources */,
|
||||
B5E294DE2349F8E7003E5956 /* SnapshotResult.swift in Sources */,
|
||||
B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B50564D42350CC3100482308 /* PropertyProtocol.swift in Sources */,
|
||||
B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
@@ -2455,7 +2440,6 @@
|
||||
82BA18AF1C4BBD3100A0916E /* CoreStore+Transaction.swift in Sources */,
|
||||
82BA18CB1C4BBD6400A0916E /* NSManagedObject+Convenience.swift in Sources */,
|
||||
82BA18B51C4BBD3F00A0916E /* BaseDataTransaction+Querying.swift in Sources */,
|
||||
B5F335592348D76300FD649F /* LiveResult.swift in Sources */,
|
||||
B501FDDF1CA8D05000BE22EF /* CSSectionBy.swift in Sources */,
|
||||
B5BF7FAE234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */,
|
||||
B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
|
||||
@@ -2477,7 +2461,7 @@
|
||||
B5E8A72121C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */,
|
||||
B50E175D2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
|
||||
B5474D162227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
|
||||
B501322B2346A9AE00FC238B /* LiveList.swift in Sources */,
|
||||
B501322B2346A9AE00FC238B /* ListPublisher.swift in Sources */,
|
||||
B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5215CAF1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
@@ -2507,7 +2491,7 @@
|
||||
B5220E111D0DA6AB009BC71E /* ListObserverTests.swift in Sources */,
|
||||
B5519A411CA1B17B002BEF78 /* ErrorTests.swift in Sources */,
|
||||
B525577D1D0291FE00E51965 /* GroupByTests.swift in Sources */,
|
||||
B5D8CA7D2346EC610055D7D1 /* LiveListTests.swift in Sources */,
|
||||
B5D8CA7D2346EC610055D7D1 /* ListPublisherTests.swift in Sources */,
|
||||
B52557751D02791400E51965 /* WhereTests.swift in Sources */,
|
||||
B5DC47C71C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
|
||||
B5DBE2E01C9939E100B5CEFA /* BridgingTests.m in Sources */,
|
||||
@@ -2553,7 +2537,7 @@
|
||||
B52DD1951BE1F92500949AFE /* CoreStoreError.swift in Sources */,
|
||||
B56923FD1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
|
||||
B55514ED1EED8BF900BAB888 /* From+Querying.swift in Sources */,
|
||||
B5BF7FC4234D7B2E0070E741 /* LiveObject.swift in Sources */,
|
||||
B5BF7FC4234D7B2E0070E741 /* ObjectPublisher.swift in Sources */,
|
||||
B596BBBE1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B55BB4D7235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
@@ -2576,7 +2560,6 @@
|
||||
B52DD1A11BE1F92C00949AFE /* DataStack+Transaction.swift in Sources */,
|
||||
B5220E1C1D130801009BC71E /* Internals.FetchedResultsControllerDelegate.swift in Sources */,
|
||||
B5BF7FCE234D80910070E741 /* Internals.LazyNonmutating.swift in Sources */,
|
||||
B5E294E02349F8E7003E5956 /* SnapshotResult.swift in Sources */,
|
||||
B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B50564D62350CC3100482308 /* PropertyProtocol.swift in Sources */,
|
||||
B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
|
||||
@@ -2679,7 +2662,6 @@
|
||||
B5220E191D130761009BC71E /* ListMonitor.swift in Sources */,
|
||||
B5220E181D130711009BC71E /* ObjectObserver.swift in Sources */,
|
||||
B5220E251D13088E009BC71E /* ListObserver.swift in Sources */,
|
||||
B5F3355B2348D76500FD649F /* LiveResult.swift in Sources */,
|
||||
B538BA7A1D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
|
||||
B5BF7FB0234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */,
|
||||
B51260821E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */,
|
||||
@@ -2701,7 +2683,7 @@
|
||||
B5E8A72321C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */,
|
||||
B50E175F2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
|
||||
B5474D182227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
|
||||
B501322E2346A9B100FC238B /* LiveList.swift in Sources */,
|
||||
B501322E2346A9B100FC238B /* ListPublisher.swift in Sources */,
|
||||
B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5215CB11FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
@@ -2731,7 +2713,7 @@
|
||||
B5220E271D1308D1009BC71E /* ObjectObserverTests.swift in Sources */,
|
||||
B525577E1D0291FE00E51965 /* GroupByTests.swift in Sources */,
|
||||
B52557761D02791400E51965 /* WhereTests.swift in Sources */,
|
||||
B5D8CA7E2346EC610055D7D1 /* LiveListTests.swift in Sources */,
|
||||
B5D8CA7E2346EC610055D7D1 /* ListPublisherTests.swift in Sources */,
|
||||
B5DC47C81C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
|
||||
B5DBE2E11C9939E100B5CEFA /* BridgingTests.m in Sources */,
|
||||
B5220E0E1D0D0D19009BC71E /* ImportTests.swift in Sources */,
|
||||
@@ -2777,7 +2759,7 @@
|
||||
B5ECDC021CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
B56923FC1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
|
||||
B55514EC1EED8BF900BAB888 /* From+Querying.swift in Sources */,
|
||||
B5BF7FC3234D7B2E0070E741 /* LiveObject.swift in Sources */,
|
||||
B5BF7FC3234D7B2E0070E741 /* ObjectPublisher.swift in Sources */,
|
||||
B596BBBD1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDC081CA8138100C7F112 /* CSOrderBy.swift in Sources */,
|
||||
B55BB4D6235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
@@ -2800,7 +2782,6 @@
|
||||
B5ECDC201CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
|
||||
B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B5BF7FCD234D80910070E741 /* Internals.LazyNonmutating.swift in Sources */,
|
||||
B5E294DF2349F8E7003E5956 /* SnapshotResult.swift in Sources */,
|
||||
B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B50564D52350CC3100482308 /* PropertyProtocol.swift in Sources */,
|
||||
B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
@@ -2903,7 +2884,6 @@
|
||||
B5DE522D230BD7D600A22534 /* Internals.swift in Sources */,
|
||||
B56321851BD65216006C9394 /* CoreStore+Logging.swift in Sources */,
|
||||
B56321921BD65216006C9394 /* BaseDataTransaction+Querying.swift in Sources */,
|
||||
B5F3355A2348D76500FD649F /* LiveResult.swift in Sources */,
|
||||
B501FDE01CA8D05000BE22EF /* CSSectionBy.swift in Sources */,
|
||||
B5BF7FAF234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */,
|
||||
B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
|
||||
@@ -2925,7 +2905,7 @@
|
||||
B5E8A72221C1015300EF006A /* CoreStoreObject+Observing.swift in Sources */,
|
||||
B50E175E2351848E004F033C /* Internals.DiffableDataUIDispatcher.DiffResult.swift in Sources */,
|
||||
B5474D172227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
|
||||
B501322D2346A9B000FC238B /* LiveList.swift in Sources */,
|
||||
B501322D2346A9B000FC238B /* ListPublisher.swift in Sources */,
|
||||
B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5215CB01FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
|
||||
@@ -717,7 +717,7 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1822" y="2013"/>
|
||||
</scene>
|
||||
<!--LiveList-->
|
||||
<!--ListPublisher-->
|
||||
<scene sceneID="gkX-bd-Rel">
|
||||
<objects>
|
||||
<tableViewController id="3AE-ED-0oj" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
@@ -768,7 +768,7 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
<extendedEdge key="edgesForExtendedLayout" top="YES"/>
|
||||
<navigationItem key="navigationItem" title="LiveList" id="5kj-jr-HoL"/>
|
||||
<navigationItem key="navigationItem" title="ListPublisher" id="5kj-jr-HoL"/>
|
||||
<connections>
|
||||
<segue destination="dX3-kR-CYC" kind="show" identifier="ObjectObserverDemoViewController" id="hyN-De-zte"/>
|
||||
</connections>
|
||||
@@ -898,7 +898,7 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="4404" y="1144.5"/>
|
||||
</scene>
|
||||
<!--LiveList-->
|
||||
<!--ListPublisher-->
|
||||
<scene sceneID="CXQ-vG-dtK">
|
||||
<objects>
|
||||
<collectionViewController id="EKY-1g-ALK" customClass="CollectionViewDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
@@ -963,7 +963,7 @@
|
||||
<outlet property="delegate" destination="EKY-1g-ALK" id="r9k-Fz-mWc"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<navigationItem key="navigationItem" title="LiveList" id="goy-Zu-94A"/>
|
||||
<navigationItem key="navigationItem" title="ListPublisher" id="goy-Zu-94A"/>
|
||||
<connections>
|
||||
<segue destination="dX3-kR-CYC" kind="show" identifier="ObjectObserverDemoViewController" id="k4E-dJ-1lz"/>
|
||||
</connections>
|
||||
|
||||
@@ -75,14 +75,14 @@ final class CollectionViewDemoViewController: UICollectionViewController {
|
||||
}
|
||||
}
|
||||
)
|
||||
ColorsDemo.palettes.addObserver(self) { [weak self] (liveList) in
|
||||
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
|
||||
|
||||
guard let self = self else {
|
||||
|
||||
return
|
||||
}
|
||||
self.filterBarButton?.title = ColorsDemo.filter.rawValue
|
||||
self.dataSource?.apply(liveList.snapshot, animatingDifferences: true)
|
||||
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
|
||||
}
|
||||
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ final class CollectionViewDemoViewController: UICollectionViewController {
|
||||
|
||||
switch (segue.identifier, segue.destination, sender) {
|
||||
|
||||
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as LiveObject<Palette>):
|
||||
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
|
||||
destinationViewController.setPalette(palette)
|
||||
|
||||
default:
|
||||
|
||||
@@ -75,9 +75,9 @@ struct ColorsDemo {
|
||||
return dataStack
|
||||
}()
|
||||
|
||||
static let palettes: LiveList<Palette> = {
|
||||
static let palettes: ListPublisher<Palette> = {
|
||||
|
||||
return ColorsDemo.stack.liveList(
|
||||
return ColorsDemo.stack.listPublisher(
|
||||
From<Palette>()
|
||||
.sectionBy(\.colorName)
|
||||
.orderBy(.ascending(\.hue))
|
||||
|
||||
@@ -87,14 +87,14 @@ final class ListObserverDemoViewController: UITableViewController {
|
||||
return cell
|
||||
}
|
||||
)
|
||||
ColorsDemo.palettes.addObserver(self) { [weak self] (liveList) in
|
||||
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
|
||||
|
||||
guard let self = self else {
|
||||
|
||||
return
|
||||
}
|
||||
self.filterBarButton?.title = ColorsDemo.filter.rawValue
|
||||
self.dataSource?.apply(liveList.snapshot, animatingDifferences: true)
|
||||
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
|
||||
}
|
||||
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
|
||||
}
|
||||
@@ -105,7 +105,7 @@ final class ListObserverDemoViewController: UITableViewController {
|
||||
|
||||
switch (segue.identifier, segue.destination, sender) {
|
||||
|
||||
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as LiveObject<Palette>):
|
||||
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
|
||||
destinationViewController.setPalette(palette)
|
||||
|
||||
default:
|
||||
|
||||
@@ -25,7 +25,7 @@ final class SwiftUIContainerViewController: UIViewController {
|
||||
|
||||
let hostingController = UIHostingController(
|
||||
rootView: SwiftUIView(
|
||||
palettes: ColorsDemo.stack.liveList(
|
||||
palettes: ColorsDemo.stack.listPublisher(
|
||||
From<Palette>()
|
||||
.sectionBy(\.colorName)
|
||||
.orderBy(.ascending(\.hue))
|
||||
|
||||
@@ -18,7 +18,7 @@ struct SwiftUIView: View {
|
||||
var dataStack: DataStack
|
||||
|
||||
@ObservedObject
|
||||
var palettes: LiveList<Palette>
|
||||
var palettes: ListPublisher<Palette>
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
@@ -92,7 +92,7 @@ struct SwiftUIView: View {
|
||||
content: {
|
||||
Alert(
|
||||
title: Text("SwiftUI Binding Demo"),
|
||||
message: Text("This demo shows how to bind to LiveList and to CoreStoreObject when using SwiftUI"),
|
||||
message: Text("This demo shows how to bind to ListPublisher and to CoreStoreObject when using SwiftUI"),
|
||||
dismissButton: .cancel(Text("OK"))
|
||||
)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ struct SwiftUIView: View {
|
||||
struct ColorCell: View {
|
||||
|
||||
@ObservedObject
|
||||
var palette: LiveObject<Palette>
|
||||
var palette: ObjectPublisher<Palette>
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
@@ -131,13 +131,13 @@ struct DetailView: View {
|
||||
var dataStack: DataStack
|
||||
|
||||
@ObservedObject
|
||||
var palette: LiveObject<Palette>
|
||||
var palette: ObjectPublisher<Palette>
|
||||
|
||||
@State var hue: Float = 0
|
||||
@State var saturation: Float = 0
|
||||
@State var brightness: Float = 0
|
||||
|
||||
init(palette: LiveObject<Palette>) {
|
||||
init(palette: ObjectPublisher<Palette>) {
|
||||
|
||||
self.palette = palette
|
||||
self.hue = Float(palette.hue ?? 0)
|
||||
@@ -166,7 +166,7 @@ struct SwiftUIView_Previews: PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
SwiftUIView(
|
||||
palettes: ColorsDemo.stack.liveList(
|
||||
palettes: ColorsDemo.stack.listPublisher(
|
||||
From<Palette>()
|
||||
.sectionBy(\.colorName)
|
||||
.orderBy(.ascending(\.hue))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// LiveListTests.swift
|
||||
// ListPublisherTests.swift
|
||||
// CoreStore iOS
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
@@ -31,18 +31,18 @@ import XCTest
|
||||
import CoreStore
|
||||
|
||||
|
||||
// MARK: - LiveListTests
|
||||
// MARK: - ListPublisherTests
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
class LiveListTests: BaseTestDataTestCase {
|
||||
class ListPublisherTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatLiveLists_CanReceiveInsertNotifications() {
|
||||
dynamic func test_ThatListPublishers_CanReceiveInsertNotifications() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
// let observer = TestListObserver()
|
||||
let liveList = stack.liveList(
|
||||
let listPublisher = stack.listPublisher(
|
||||
From<TestEntity1>(),
|
||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||
@@ -160,7 +160,7 @@ class LiveListTests: BaseTestDataTestCase {
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
|
||||
withExtendedLifetime(liveList, {})
|
||||
withExtendedLifetime(listPublisher, {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#if canImport(Combine)
|
||||
import Combine
|
||||
|
||||
// MARK: - LiveList: ObservableObject
|
||||
// MARK: - ListPublisher: ObservableObject
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
extension CoreStoreObject: ObservableObject {
|
||||
|
||||
@@ -34,24 +34,24 @@ import CoreData
|
||||
extension DataStack {
|
||||
|
||||
/**
|
||||
Creates a `LiveObject` for the specified `DynamicObject`. Multiple objects may then register themselves to be notified when changes are made to the `DynamicObject`.
|
||||
Creates a `ObjectPublisher` for the specified `DynamicObject`. Multiple objects may then register themselves to be notified when changes are made to the `DynamicObject`.
|
||||
|
||||
- parameter object: the `DynamicObject` to observe changes from
|
||||
- returns: a `LiveObject` that broadcasts changes to `object`
|
||||
- returns: a `ObjectPublisher` that broadcasts changes to `object`
|
||||
*/
|
||||
public func liveObject<O: DynamicObject>(_ object: O) -> LiveObject<O> {
|
||||
public func objectPublisher<O: DynamicObject>(_ object: O) -> ObjectPublisher<O> {
|
||||
|
||||
return LiveObject<O>(objectID: object.cs_id(), context: self.unsafeContext())
|
||||
return ObjectPublisher<O>(objectID: object.cs_id(), context: self.unsafeContext())
|
||||
}
|
||||
|
||||
public func liveList<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> LiveList<D> {
|
||||
public func listPublisher<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> ListPublisher<D> {
|
||||
|
||||
return self.liveList(from, fetchClauses)
|
||||
return self.listPublisher(from, fetchClauses)
|
||||
}
|
||||
|
||||
public func liveList<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> LiveList<D> {
|
||||
public func listPublisher<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> ListPublisher<D> {
|
||||
|
||||
return LiveList(
|
||||
return ListPublisher(
|
||||
dataStack: self,
|
||||
from: from,
|
||||
sectionBy: nil,
|
||||
@@ -61,31 +61,31 @@ extension DataStack {
|
||||
|
||||
Internals.assert(
|
||||
fetchRequest.sortDescriptors?.isEmpty == false,
|
||||
"An \(Internals.typeName(LiveList<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
"An \(Internals.typeName(ListPublisher<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<B: FetchChainableBuilderType>(_ clauseChain: B) -> LiveList<B.ObjectType> {
|
||||
public func listPublisher<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListPublisher<B.ObjectType> {
|
||||
|
||||
return self.liveList(
|
||||
return self.listPublisher(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<D>(createAsynchronously: @escaping (LiveList<D>) -> Void, _ from: From<D>, _ fetchClauses: FetchClause...) {
|
||||
public func listPublisher<D>(createAsynchronously: @escaping (ListPublisher<D>) -> Void, _ from: From<D>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.liveList(
|
||||
self.listPublisher(
|
||||
createAsynchronously: createAsynchronously,
|
||||
from, fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<D>(createAsynchronously: @escaping (LiveList<D>) -> Void, _ from: From<D>, _ fetchClauses: [FetchClause]) {
|
||||
public func listPublisher<D>(createAsynchronously: @escaping (ListPublisher<D>) -> Void, _ from: From<D>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
_ = LiveList(
|
||||
_ = ListPublisher(
|
||||
dataStack: self,
|
||||
from: from,
|
||||
sectionBy: nil,
|
||||
@@ -95,25 +95,25 @@ extension DataStack {
|
||||
|
||||
Internals.assert(
|
||||
fetchRequest.sortDescriptors?.isEmpty == false,
|
||||
"An \(Internals.typeName(LiveList<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
"An \(Internals.typeName(ListPublisher<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
)
|
||||
},
|
||||
createAsynchronously: createAsynchronously
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> LiveList<D> {
|
||||
public func listPublisher<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListPublisher<D> {
|
||||
|
||||
return self.liveList(
|
||||
return self.listPublisher(
|
||||
from,
|
||||
sectionBy,
|
||||
fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> LiveList<D> {
|
||||
public func listPublisher<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListPublisher<D> {
|
||||
|
||||
return LiveList(
|
||||
return ListPublisher(
|
||||
dataStack: self,
|
||||
from: from,
|
||||
sectionBy: sectionBy,
|
||||
@@ -123,24 +123,24 @@ extension DataStack {
|
||||
|
||||
Internals.assert(
|
||||
fetchRequest.sortDescriptors?.isEmpty == false,
|
||||
"An \(Internals.typeName(LiveList<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
"An \(Internals.typeName(ListPublisher<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> LiveList<B.ObjectType> {
|
||||
public func listPublisher<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListPublisher<B.ObjectType> {
|
||||
|
||||
return self.liveList(
|
||||
return self.listPublisher(
|
||||
clauseChain.from,
|
||||
clauseChain.sectionBy,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<D>(createAsynchronously: @escaping (LiveList<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
|
||||
public func listPublisher<D>(createAsynchronously: @escaping (ListPublisher<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.liveList(
|
||||
self.listPublisher(
|
||||
createAsynchronously: createAsynchronously,
|
||||
from,
|
||||
sectionBy,
|
||||
@@ -148,9 +148,9 @@ extension DataStack {
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<D>(createAsynchronously: @escaping (LiveList<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
|
||||
public func listPublisher<D>(createAsynchronously: @escaping (ListPublisher<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
_ = LiveList(
|
||||
_ = ListPublisher(
|
||||
dataStack: self,
|
||||
from: from,
|
||||
sectionBy: sectionBy,
|
||||
@@ -160,16 +160,16 @@ extension DataStack {
|
||||
|
||||
Internals.assert(
|
||||
fetchRequest.sortDescriptors?.isEmpty == false,
|
||||
"An \(Internals.typeName(LiveList<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
"An \(Internals.typeName(ListPublisher<D>.self)) requires a sort information. Specify from a \(Internals.typeName(OrderBy<D>.self)) clause or any custom \(Internals.typeName(FetchClause.self)) that provides a sort descriptor."
|
||||
)
|
||||
},
|
||||
createAsynchronously: createAsynchronously
|
||||
)
|
||||
}
|
||||
|
||||
public func liveList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (LiveList<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
public func listPublisher<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListPublisher<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
self.liveList(
|
||||
self.listPublisher(
|
||||
createAsynchronously: createAsynchronously,
|
||||
clauseChain.from,
|
||||
clauseChain.sectionBy,
|
||||
|
||||
@@ -67,14 +67,14 @@ import CoreData
|
||||
In the example above, both `person1` and `person2` will contain the object at section=2, index=3.
|
||||
*/
|
||||
@available(macOS 10.12, *)
|
||||
public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
public final class ListMonitor<O: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Public (Accessors)
|
||||
|
||||
/**
|
||||
The type for the objects contained bye the `ListMonitor`
|
||||
*/
|
||||
public typealias ObjectType = D
|
||||
public typealias ObjectType = O
|
||||
|
||||
/**
|
||||
Returns the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `monitorList(_:)`.
|
||||
@@ -82,7 +82,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter index: the index of the object. Using an index above the valid range will raise an exception.
|
||||
- returns: the `DynamicObject` at the specified index
|
||||
*/
|
||||
public subscript(index: Int) -> ObjectType {
|
||||
public subscript(index: Int) -> O {
|
||||
|
||||
Internals.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
@@ -90,7 +90,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
if self.isSectioned {
|
||||
|
||||
return ObjectType.cs_fromRaw(object: (self.fetchedResultsController.fetchedObjects as NSArray?)![index] as! NSManagedObject)
|
||||
return O.cs_fromRaw(object: (self.fetchedResultsController.fetchedObjects as NSArray?)![index] as! NSManagedObject)
|
||||
}
|
||||
return self[0, index]
|
||||
}
|
||||
@@ -101,14 +101,14 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter index: the index for the object. Using an index above the valid range will return `nil`.
|
||||
- returns: the `DynamicObject` at the specified index, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeIndex index: Int) -> ObjectType? {
|
||||
public subscript(safeIndex index: Int) -> O? {
|
||||
|
||||
if self.isSectioned {
|
||||
|
||||
let fetchedObjects = (self.fetchedResultsController.fetchedObjects as NSArray?)!
|
||||
if index < fetchedObjects.count && index >= 0 {
|
||||
|
||||
return ObjectType.cs_fromRaw(object: fetchedObjects[index] as! NSManagedObject)
|
||||
return O.cs_fromRaw(object: fetchedObjects[index] as! NSManagedObject)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will raise an exception.
|
||||
- returns: the `DynamicObject` at the specified section and item index
|
||||
*/
|
||||
public subscript(sectionIndex: Int, itemIndex: Int) -> ObjectType {
|
||||
public subscript(sectionIndex: Int, itemIndex: Int) -> O {
|
||||
|
||||
return self[IndexPath(indexes: [sectionIndex, itemIndex])]
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will return `nil`.
|
||||
- returns: the `DynamicObject` at the specified section and item index, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeSectionIndex sectionIndex: Int, safeItemIndex itemIndex: Int) -> ObjectType? {
|
||||
public subscript(safeSectionIndex sectionIndex: Int, safeItemIndex itemIndex: Int) -> O? {
|
||||
|
||||
guard let section = self.sectionInfo(safelyAt: sectionIndex) else {
|
||||
|
||||
@@ -153,13 +153,13 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter indexPath: the `IndexPath` for the object. Using an `indexPath` with an invalid range will raise an exception.
|
||||
- returns: the `DynamicObject` at the specified index path
|
||||
*/
|
||||
public subscript(indexPath: IndexPath) -> ObjectType {
|
||||
public subscript(indexPath: IndexPath) -> O {
|
||||
|
||||
Internals.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(Internals.typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return ObjectType.cs_fromRaw(object: self.fetchedResultsController.object(at: indexPath))
|
||||
return O.cs_fromRaw(object: self.fetchedResultsController.object(at: indexPath))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,7 +168,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter indexPath: the `IndexPath` for the object. Using an `indexPath` with an invalid range will return `nil`.
|
||||
- returns: the `DynamicObject` at the specified index path, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeIndexPath indexPath: IndexPath) -> ObjectType? {
|
||||
public subscript(safeIndexPath indexPath: IndexPath) -> O? {
|
||||
|
||||
return self[
|
||||
safeSectionIndex: indexPath[0],
|
||||
@@ -345,7 +345,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter object: the `DynamicObject` to search the index of
|
||||
- returns: the index of the `DynamicObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
|
||||
*/
|
||||
public func index(of object: ObjectType) -> Int? {
|
||||
public func index(of object: O) -> Int? {
|
||||
|
||||
Internals.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
@@ -364,7 +364,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
- parameter object: the `DynamicObject` to search the index of
|
||||
- returns: the `IndexPath` of the `DynamicObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
|
||||
*/
|
||||
public func indexPath(of object: ObjectType) -> IndexPath? {
|
||||
public func indexPath(of object: O) -> IndexPath? {
|
||||
|
||||
Internals.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
@@ -387,7 +387,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
- parameter observer: a `ListObserver` to send change notifications to
|
||||
*/
|
||||
public func addObserver<U: ListObserver>(_ observer: U) where U.ListEntityType == ObjectType {
|
||||
public func addObserver<U: ListObserver>(_ observer: U) where U.ListEntityType == O {
|
||||
|
||||
self.unregisterObserver(observer)
|
||||
self.registerObserver(
|
||||
@@ -422,7 +422,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
- parameter observer: a `ListObjectObserver` to send change notifications to
|
||||
*/
|
||||
public func addObserver<U: ListObjectObserver>(_ observer: U) where U.ListEntityType == ObjectType {
|
||||
public func addObserver<U: ListObjectObserver>(_ observer: U) where U.ListEntityType == O {
|
||||
|
||||
self.unregisterObserver(observer)
|
||||
self.registerObserver(
|
||||
@@ -476,7 +476,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
- parameter observer: a `ListSectionObserver` to send change notifications to
|
||||
*/
|
||||
public func addObserver<U: ListSectionObserver>(_ observer: U) where U.ListEntityType == ObjectType {
|
||||
public func addObserver<U: ListSectionObserver>(_ observer: U) where U.ListEntityType == O {
|
||||
|
||||
self.unregisterObserver(observer)
|
||||
self.registerObserver(
|
||||
@@ -537,7 +537,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
- parameter observer: a `ListObserver` to unregister notifications to
|
||||
*/
|
||||
public func removeObserver<U: ListObserver>(_ observer: U) where U.ListEntityType == ObjectType {
|
||||
public func removeObserver<U: ListObserver>(_ observer: U) where U.ListEntityType == O {
|
||||
|
||||
self.unregisterObserver(observer)
|
||||
}
|
||||
@@ -597,7 +597,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == (lhs: ListMonitor<ObjectType>, rhs: ListMonitor<ObjectType>) -> Bool {
|
||||
public static func == (lhs: ListMonitor<O>, rhs: ListMonitor<O>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -607,7 +607,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= (lhs: ListMonitor<ObjectType>, rhs: ListMonitor<ObjectType>) -> Bool {
|
||||
public static func ~= (lhs: ListMonitor<O>, rhs: ListMonitor<O>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -628,7 +628,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal convenience init(dataStack: DataStack, from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: dataStack.mainContext,
|
||||
@@ -640,7 +640,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<ObjectType>) -> Void) {
|
||||
internal convenience init(dataStack: DataStack, from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<O>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: dataStack.mainContext,
|
||||
@@ -652,7 +652,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: unsafeTransaction.context,
|
||||
@@ -664,7 +664,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<ObjectType>) -> Void) {
|
||||
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<O>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: unsafeTransaction.context,
|
||||
@@ -676,7 +676,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<ObjectType>) -> Void) {
|
||||
internal func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<O>) -> Void) {
|
||||
|
||||
Internals.setAssociatedRetainedObject(
|
||||
Internals.NotificationObserver(
|
||||
@@ -696,7 +696,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func registerObjectNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<ObjectType>, _ object: ObjectType, _ indexPath: IndexPath?, _ newIndexPath: IndexPath?) -> Void) {
|
||||
internal func registerObjectNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<O>, _ object: O, _ indexPath: IndexPath?, _ newIndexPath: IndexPath?) -> Void) {
|
||||
|
||||
Internals.setAssociatedRetainedObject(
|
||||
Internals.NotificationObserver(
|
||||
@@ -712,7 +712,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
}
|
||||
callback(
|
||||
self,
|
||||
ObjectType.cs_fromRaw(object: rawObject),
|
||||
O.cs_fromRaw(object: rawObject),
|
||||
userInfo[String(describing: IndexPath.self)] as? IndexPath,
|
||||
userInfo["\(String(describing: IndexPath.self)).New"] as? IndexPath
|
||||
)
|
||||
@@ -723,7 +723,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func registerSectionNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<ObjectType>, _ sectionInfo: NSFetchedResultsSectionInfo, _ sectionIndex: Int) -> Void) {
|
||||
internal func registerSectionNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor<O>, _ sectionInfo: NSFetchedResultsSectionInfo, _ sectionIndex: Int) -> Void) {
|
||||
|
||||
Internals.setAssociatedRetainedObject(
|
||||
Internals.NotificationObserver(
|
||||
@@ -746,7 +746,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, willChange: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>) -> Void, didChange: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>) -> Void, willRefetch: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>) -> Void, didRefetch: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>) -> Void) {
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, willChange: @escaping (_ observer: U, _ monitor: ListMonitor<O>) -> Void, didChange: @escaping (_ observer: U, _ monitor: ListMonitor<O>) -> Void, willRefetch: @escaping (_ observer: U, _ monitor: ListMonitor<O>) -> Void, didRefetch: @escaping (_ observer: U, _ monitor: ListMonitor<O>) -> Void) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -806,7 +806,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, didInsertObject: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>, _ object: ObjectType, _ toIndexPath: IndexPath) -> Void, didDeleteObject: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>, _ object: ObjectType, _ fromIndexPath: IndexPath) -> Void, didUpdateObject: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>, _ object: ObjectType, _ atIndexPath: IndexPath) -> Void, didMoveObject: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>, _ object: ObjectType, _ fromIndexPath: IndexPath, _ toIndexPath: IndexPath) -> Void) {
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, didInsertObject: @escaping (_ observer: U, _ monitor: ListMonitor<O>, _ object: O, _ toIndexPath: IndexPath) -> Void, didDeleteObject: @escaping (_ observer: U, _ monitor: ListMonitor<O>, _ object: O, _ fromIndexPath: IndexPath) -> Void, didUpdateObject: @escaping (_ observer: U, _ monitor: ListMonitor<O>, _ object: O, _ atIndexPath: IndexPath) -> Void, didMoveObject: @escaping (_ observer: U, _ monitor: ListMonitor<O>, _ object: O, _ fromIndexPath: IndexPath, _ toIndexPath: IndexPath) -> Void) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -867,7 +867,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, didInsertSection: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>, _ sectionInfo: NSFetchedResultsSectionInfo, _ toIndex: Int) -> Void, didDeleteSection: @escaping (_ observer: U, _ monitor: ListMonitor<ObjectType>, _ sectionInfo: NSFetchedResultsSectionInfo, _ fromIndex: Int) -> Void) {
|
||||
internal func registerObserver<U: AnyObject>(_ observer: U, didInsertSection: @escaping (_ observer: U, _ monitor: ListMonitor<O>, _ sectionInfo: NSFetchedResultsSectionInfo, _ toIndex: Int) -> Void, didDeleteSection: @escaping (_ observer: U, _ monitor: ListMonitor<O>, _ sectionInfo: NSFetchedResultsSectionInfo, _ fromIndex: Int) -> Void) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -1052,7 +1052,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
private static func recreateFetchedResultsController(context: NSManagedObjectContext, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) -> (controller: Internals.CoreStoreFetchedResultsController, delegate: Internals.FetchedResultsControllerDelegate) {
|
||||
private static func recreateFetchedResultsController(context: NSManagedObjectContext, from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) -> (controller: Internals.CoreStoreFetchedResultsController, delegate: Internals.FetchedResultsControllerDelegate) {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObject>()
|
||||
fetchRequest.fetchLimit = 0
|
||||
@@ -1075,10 +1075,10 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
return (fetchedResultsController, fetchedResultsControllerDelegate)
|
||||
}
|
||||
|
||||
private let from: From<ObjectType>
|
||||
private let sectionBy: SectionBy<ObjectType>?
|
||||
private let from: From<O>
|
||||
private let sectionBy: SectionBy<O>?
|
||||
|
||||
private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<ObjectType>) -> Void)?) {
|
||||
private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<O>) -> Void)?) {
|
||||
|
||||
self.isSectioned = (sectionBy != nil)
|
||||
self.from = from
|
||||
@@ -1173,77 +1173,26 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
try! self.fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "hasObjects(in:)")
|
||||
public func hasObjectsInSection(_ section: Int) -> Bool {
|
||||
|
||||
return self.hasObjects(in: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "numberOfObjects(in:)")
|
||||
public func numberOfObjectsInSection(_ section: Int) -> Int {
|
||||
|
||||
return self.numberOfObjects(in: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "numberOfObjects(safelyIn:)")
|
||||
public func numberOfObjectsInSection(safeSectionIndex section: Int) -> Int? {
|
||||
|
||||
return self.numberOfObjects(safelyIn: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "sectionInfo(at:)")
|
||||
public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo {
|
||||
|
||||
return self.sectionInfo(at: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "sectionInfo(safelyAt:)")
|
||||
public func sectionInfoAtIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
|
||||
|
||||
return self.sectionInfo(safelyAt: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "targetSection(forSectionIndexTitle:at:)")
|
||||
public func targetSectionForSectionIndex(title: String, index: Int) -> Int {
|
||||
|
||||
return self.targetSection(forSectionIndexTitle: title, at: index)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "index(of:)")
|
||||
public func indexOf(_ object: ObjectType) -> Int? {
|
||||
|
||||
return self.index(of: object)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "indexPath(of:)")
|
||||
public func indexPathOf(_ object: ObjectType) -> IndexPath? {
|
||||
|
||||
return self.indexPath(of: object)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListMonitor where ListMonitor.ObjectType: NSManagedObject
|
||||
// MARK: - ListMonitor where O: NSManagedObject
|
||||
|
||||
@available(macOS 10.12, *)
|
||||
extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
|
||||
extension ListMonitor where O: NSManagedObject {
|
||||
|
||||
/**
|
||||
Returns all objects in all sections
|
||||
|
||||
- returns: all objects in all sections
|
||||
*/
|
||||
public func objectsInAllSections() -> [ObjectType] {
|
||||
public func objectsInAllSections() -> [O] {
|
||||
|
||||
Internals.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(Internals.typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return (self.fetchedResultsController.dynamicCast() as NSFetchedResultsController<ObjectType>).fetchedObjects ?? []
|
||||
return (self.fetchedResultsController.dynamicCast() as NSFetchedResultsController<O>).fetchedObjects ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1252,9 +1201,9 @@ extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
|
||||
- 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 objects(in section: Int) -> [ObjectType] {
|
||||
public func objects(in section: Int) -> [O] {
|
||||
|
||||
return (self.sectionInfo(at: section).objects as! [ObjectType]?) ?? []
|
||||
return (self.sectionInfo(at: section).objects as! [O]?) ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1263,46 +1212,46 @@ extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objects(safelyIn section: Int) -> [ObjectType]? {
|
||||
public func objects(safelyIn section: Int) -> [O]? {
|
||||
|
||||
return self.sectionInfo(safelyAt: section)?.objects as! [ObjectType]?
|
||||
return self.sectionInfo(safelyAt: section)?.objects as! [O]?
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "objects(in:)")
|
||||
public func objectsInSection(_ section: Int) -> [ObjectType] {
|
||||
public func objectsInSection(_ section: Int) -> [O] {
|
||||
|
||||
return self.objects(in: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "objects(safelyIn:)")
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [ObjectType]? {
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [O]? {
|
||||
|
||||
return self.objects(safelyIn: section)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListMonitor where ListMonitor.ObjectType: CoreStoreObject
|
||||
// MARK: - ListMonitor where O: CoreStoreObject
|
||||
|
||||
@available(macOS 10.12, *)
|
||||
extension ListMonitor where ListMonitor.ObjectType: CoreStoreObject {
|
||||
extension ListMonitor where O: CoreStoreObject {
|
||||
|
||||
/**
|
||||
Returns all objects in all sections
|
||||
|
||||
- returns: all objects in all sections
|
||||
*/
|
||||
public func objectsInAllSections() -> [ObjectType] {
|
||||
public func objectsInAllSections() -> [O] {
|
||||
|
||||
Internals.assert(
|
||||
!self.isPendingRefetch || Thread.isMainThread,
|
||||
"Attempted to access a \(Internals.typeName(self)) outside the main thread while a refetch is in progress."
|
||||
)
|
||||
return (self.fetchedResultsController.fetchedObjects ?? [])
|
||||
.map(ObjectType.cs_fromRaw)
|
||||
.map(O.cs_fromRaw)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1311,10 +1260,10 @@ extension ListMonitor where ListMonitor.ObjectType: CoreStoreObject {
|
||||
- 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 objects(in section: Int) -> [ObjectType] {
|
||||
public func objects(in section: Int) -> [O] {
|
||||
|
||||
return (self.sectionInfo(at: section).objects ?? [])
|
||||
.map({ ObjectType.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
.map({ O.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1323,26 +1272,17 @@ extension ListMonitor where ListMonitor.ObjectType: CoreStoreObject {
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objects(safelyIn section: Int) -> [ObjectType]? {
|
||||
public func objects(safelyIn section: Int) -> [O]? {
|
||||
|
||||
return (self.sectionInfo(safelyAt: section)?.objects)?
|
||||
.map({ ObjectType.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
.map({ O.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "objects(in:)")
|
||||
public func objectsInSection(_ section: Int) -> [ObjectType] {
|
||||
|
||||
return self.objects(in: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "objects(safelyIn:)")
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [ObjectType]? {
|
||||
|
||||
return self.objects(safelyIn: section)
|
||||
}
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// LiveList.swift
|
||||
// ListPublisher.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
@@ -36,176 +36,110 @@ import SwiftUI
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - LiveList
|
||||
// MARK: - ListPublisher
|
||||
|
||||
/**
|
||||
`LiveList` tracks a diffable list of `DynamicObject` instances. Unlike `ListMonitor`s, `LiveList` are more lightweight and access objects lazily. `LiveList`s are also designed to work well with `DiffableDataSource.TableView`s and `DiffableDataSource.CollectionView`s. Objects that need to be notified of `LiveList` changes may register themselves to its `addObserver(_:_:)` method:
|
||||
`ListPublisher` tracks a diffable list of `DynamicObject` instances. Unlike `ListMonitor`s, `ListPublisher` are more lightweight and access objects lazily. Objects that need to be notified of `ListPublisher` changes may register themselves to its `addObserver(_:_:)` method:
|
||||
```
|
||||
let liveList = Shared.defaultStack.liveList(
|
||||
let listPublisher = Shared.defaultStack.listPublisher(
|
||||
From<Person>()
|
||||
.where(\.title == "Engineer")
|
||||
.orderBy(.ascending(\.lastName))
|
||||
)
|
||||
liveList.addObserver(self) { (liveList) in
|
||||
|
||||
listPublisher.addObserver(self) { (listPublisher) in
|
||||
// Handle changes
|
||||
}
|
||||
```
|
||||
The `LiveList` instance needs to be held on (retained) for as long as the list needs to be observed.
|
||||
Observers registered via `addObserver(_:_:)` are not retained. `LiveList` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
|
||||
The `ListPublisher` instance needs to be held on (retained) for as long as the list needs to be observed.
|
||||
Observers registered via `addObserver(_:_:)` are not retained. `ListPublisher` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
|
||||
|
||||
`LiveList`s may optionally be created with sections:
|
||||
`ListPublisher`s may optionally be created with sections:
|
||||
```
|
||||
let liveList = Shared.defaultStack.liveList(
|
||||
let listPublisher = Shared.defaultStack.listPublisher(
|
||||
From<Person>()
|
||||
.sectionBy(\.age") { "Age \($0)" }
|
||||
.where(\.title == "Engineer")
|
||||
.orderBy(.ascending(\.lastName))
|
||||
)
|
||||
liveList.addObserver(self) { (liveList) in
|
||||
|
||||
// Handle changes
|
||||
}
|
||||
```
|
||||
All access to the `ListPublisher` items should be done via its `snapshot` value, which is a `struct` of type `ListSnapshot<O>`. `ListSnapshot`s are also designed to work well with `DiffableDataSource.TableView`s and `DiffableDataSource.CollectionView`s. For detailed examples, refer to the documentation for `DiffableDataSource.TableView` and `DiffableDataSource.CollectionView`.
|
||||
*/
|
||||
@available(macOS 10.12, *)
|
||||
public final class LiveList<O: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Public
|
||||
public final class ListPublisher<O: DynamicObject>: Hashable {
|
||||
|
||||
public typealias SectionID = SnapshotType.SectionID
|
||||
public typealias ItemID = SnapshotType.ItemID
|
||||
// MARK: Public (Accessors)
|
||||
|
||||
public subscript(section sectionID: SectionID) -> [LiveObject<O>] {
|
||||
/**
|
||||
The `DynamicObject` type associated with this list
|
||||
*/
|
||||
public typealias ObjectType = O
|
||||
|
||||
let context = self.context
|
||||
return self.snapshot
|
||||
.itemIdentifiers(inSection: sectionID)
|
||||
.map({ context.liveObject(objectID: $0) })
|
||||
}
|
||||
/**
|
||||
The type for the section IDs
|
||||
*/
|
||||
public typealias SectionID = ListSnapshot<O>.SectionID
|
||||
|
||||
public subscript(itemID itemID: ItemID) -> LiveObject<O>? {
|
||||
/**
|
||||
The type for the item IDs
|
||||
*/
|
||||
public typealias ItemID = ListSnapshot<O>.ItemID
|
||||
|
||||
guard let validID = self.snapshot.itemIdentifiers.first(where: { $0 == itemID }) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return self.context.liveObject(objectID: validID)
|
||||
}
|
||||
|
||||
public subscript(indexPath indexPath: IndexPath) -> LiveObject<O>? {
|
||||
|
||||
let snapshot = self.snapshot
|
||||
let sectionIdentifiers = snapshot.sectionIdentifiers
|
||||
guard sectionIdentifiers.indices.contains(indexPath.section) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
let sectionID = sectionIdentifiers[indexPath.section]
|
||||
let itemIdentifiers = snapshot.itemIdentifiers(inSection: sectionID)
|
||||
guard itemIdentifiers.indices.contains(indexPath.item) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
let itemID = itemIdentifiers[indexPath.item]
|
||||
return self.context.liveObject(objectID: itemID)
|
||||
}
|
||||
|
||||
public subscript<S: Sequence>(section sectionID: SectionID, itemIndices itemIndices: S) -> [LiveObject<O>] where S.Element == Int {
|
||||
|
||||
let context = self.context
|
||||
let itemIDs = self.snapshot.itemIdentifiers(inSection: sectionID)
|
||||
return itemIndices.map { position in
|
||||
|
||||
let itemID = itemIDs[position]
|
||||
return context.liveObject(objectID: itemID)
|
||||
}
|
||||
}
|
||||
|
||||
public fileprivate(set) var snapshot: SnapshotType = .init() {
|
||||
/**
|
||||
A snapshot of the latest state of this list
|
||||
*/
|
||||
public fileprivate(set) var snapshot: ListSnapshot<O> = .init() {
|
||||
|
||||
willSet {
|
||||
|
||||
self.willChange()
|
||||
}
|
||||
didSet {
|
||||
|
||||
self.notifyObservers()
|
||||
|
||||
self.didChange()
|
||||
self.notifyObservers()
|
||||
}
|
||||
}
|
||||
|
||||
public var numberOfItems: Int {
|
||||
|
||||
return self.snapshot.numberOfItems
|
||||
}
|
||||
// MARK: Public (Observers)
|
||||
|
||||
public var numberOfSections: Int {
|
||||
/**
|
||||
Registers an object as an observer to be notified when changes to the `ListPublisher`'s snapshot occur.
|
||||
|
||||
return self.snapshot.numberOfSections
|
||||
}
|
||||
To prevent retain-cycles, `ListPublisher` only keeps `weak` references to its observers.
|
||||
|
||||
public var sectionIdentifiers: [SectionID] {
|
||||
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
|
||||
|
||||
return self.snapshot.sectionIdentifiers
|
||||
}
|
||||
Calling `addObserver(_:_:)` multiple times on the same observer is safe.
|
||||
|
||||
public var items: [LiveObject<O>] {
|
||||
- parameter observer: an object to become owner of the specified `callback`
|
||||
- parameter callback: the closure to execute when changes occur
|
||||
*/
|
||||
public func addObserver<T: AnyObject>(_ observer: T, _ callback: @escaping (ListPublisher<O>) -> Void) {
|
||||
|
||||
let context = self.context
|
||||
return self.snapshot.itemIdentifiers
|
||||
.map({ context.liveObject(objectID: $0) })
|
||||
}
|
||||
|
||||
public func numberOfItems(inSection identifier: SectionID) -> Int {
|
||||
|
||||
return self.snapshot.numberOfItems(inSection: identifier)
|
||||
}
|
||||
|
||||
public func items(inSection identifier: SectionID) -> [LiveObject<O>] {
|
||||
|
||||
let context = self.context
|
||||
return self.snapshot
|
||||
.itemIdentifiers(inSection: identifier)
|
||||
.map({ context.liveObject(objectID: $0) })
|
||||
}
|
||||
|
||||
public func items(inSection identifier: SectionID, atIndices indices: IndexSet) -> [LiveObject<O>] {
|
||||
|
||||
let context = self.context
|
||||
let itemIDs = self.snapshot.itemIdentifiers(inSection: identifier)
|
||||
return indices.map { position in
|
||||
|
||||
let itemID = itemIDs[position]
|
||||
return context.liveObject(objectID: itemID)
|
||||
}
|
||||
}
|
||||
|
||||
public func section(containingItem item: LiveObject<O>) -> SectionID? {
|
||||
|
||||
return self.snapshot.sectionIdentifier(containingItem: item.objectID())
|
||||
}
|
||||
|
||||
public func indexOfItem(_ item: LiveObject<O>) -> Int? {
|
||||
|
||||
return self.snapshot.indexOfItem(item.objectID())
|
||||
}
|
||||
|
||||
public func indexOfSection(_ identifier: SectionID) -> Int? {
|
||||
|
||||
return self.snapshot.indexOfSection(identifier)
|
||||
}
|
||||
|
||||
public func addObserver<T: AnyObject>(_ observer: T, _ callback: @escaping (LiveList<O>) -> Void) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to add an observer of type \(Internals.typeName(observer)) outside the main thread."
|
||||
)
|
||||
self.observers.setObject(
|
||||
Internals.Closure(callback),
|
||||
forKey: observer
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Unregisters an object from receiving notifications for changes to the `ListPublisher`'s snapshot.
|
||||
|
||||
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
|
||||
|
||||
- parameter observer: the object whose notifications will be unregistered
|
||||
*/
|
||||
public func removeObserver<T: AnyObject>(_ observer: T) {
|
||||
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to remove an observer of type \(Internals.typeName(observer)) outside the main thread."
|
||||
)
|
||||
self.observers.removeObject(forKey: observer)
|
||||
}
|
||||
|
||||
@@ -213,39 +147,57 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
// MARK: Public (Refetching)
|
||||
|
||||
/**
|
||||
Asks the `ListMonitor` to refetch its objects using the specified series of `FetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
|
||||
|
||||
`refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.
|
||||
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- Important: Starting CoreStore 4.0, all `FetchClause`s required by the `ListMonitor` should be provided in the arguments list of `refetch(...)`.
|
||||
Asks the `ListPublisher` to refetch its objects using the specified `FetchChainableBuilderType`. Unlike `ListMonitor`s, a `ListPublisher`'s `refetch(...)` executes immediately.
|
||||
```
|
||||
try listPublisher.refetch(
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
*/
|
||||
public func refetch(_ fetchClauses: FetchClause...) {
|
||||
public func refetch<B: FetchChainableBuilderType>(_ clauseChain: B) throws where B.ObjectType == O {
|
||||
|
||||
self.refetch(fetchClauses)
|
||||
try self.refetch(
|
||||
from: clauseChain.from,
|
||||
sectionBy: nil,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
clauseChain.fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Asks the `ListMonitor` to refetch its objects using the specified series of `FetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
|
||||
|
||||
`refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.
|
||||
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- Important: Starting CoreStore 4.0, all `FetchClause`s required by the `ListMonitor` should be provided in the arguments list of `refetch(...)`.
|
||||
Asks the `ListPublisher` to refetch its objects using the specified `SectionMonitorBuilderType`. Unlike `ListMonitor`s, a `ListPublisher`'s `refetch(...)` executes immediately.
|
||||
```
|
||||
try listPublisher.refetch(
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
*/
|
||||
public func refetch(_ fetchClauses: [FetchClause]) {
|
||||
public func refetch<B: SectionMonitorBuilderType>(_ clauseChain: B) throws where B.ObjectType == O {
|
||||
|
||||
self.refetch { (fetchRequest) in
|
||||
try self.refetch(
|
||||
from: clauseChain.from,
|
||||
sectionBy: clauseChain.sectionBy,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
|
||||
}
|
||||
clauseChain.fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Public (3rd Party Utilities)
|
||||
|
||||
/**
|
||||
Allow external libraries to store custom data in the `ListMonitor`. App code should rarely have a need for this.
|
||||
Allow external libraries to store custom data in the `ListPublisher`. App code should rarely have a need for this.
|
||||
```
|
||||
enum Static {
|
||||
static var myDataKey: Void?
|
||||
@@ -259,7 +211,7 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == (_ lhs: LiveList, _ rhs: LiveList) -> Bool {
|
||||
public static func == (_ lhs: ListPublisher, _ rhs: ListPublisher) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
@@ -271,13 +223,6 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
|
||||
hasher.combine(ObjectIdentifier(self))
|
||||
}
|
||||
|
||||
|
||||
// MARK: LiveResult
|
||||
|
||||
public typealias ObjectType = O
|
||||
|
||||
public typealias SnapshotType = ListSnapshot<O>
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
@@ -293,7 +238,7 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (LiveList<ObjectType>) -> Void) {
|
||||
internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListPublisher<ObjectType>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: dataStack.mainContext,
|
||||
@@ -315,7 +260,7 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (LiveList<ObjectType>) -> Void) {
|
||||
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListPublisher<ObjectType>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: unsafeTransaction.context,
|
||||
@@ -326,36 +271,26 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
)
|
||||
}
|
||||
|
||||
internal func refetch(_ applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal func refetch(from: From<O>, sectionBy: SectionBy<O>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void) throws {
|
||||
|
||||
self.applyFetchClauses = applyFetchClauses
|
||||
let (newFetchedResultsController, newFetchedResultsControllerDelegate) = Self.recreateFetchedResultsController(
|
||||
context: self.fetchedResultsController.managedObjectContext,
|
||||
from: from,
|
||||
sectionBy: sectionBy,
|
||||
applyFetchClauses: applyFetchClauses
|
||||
)
|
||||
|
||||
DispatchQueue.main.async { [weak self] () -> Void in
|
||||
try newFetchedResultsController.performFetchFromSpecifiedStores()
|
||||
|
||||
guard let `self` = self else {
|
||||
newFetchedResultsControllerDelegate.handler = self
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let (newFetchedResultsController, newFetchedResultsControllerDelegate) = Self.recreateFetchedResultsController(
|
||||
context: self.fetchedResultsController.managedObjectContext,
|
||||
from: self.from,
|
||||
sectionBy: self.sectionBy,
|
||||
applyFetchClauses: self.applyFetchClauses
|
||||
)
|
||||
newFetchedResultsControllerDelegate.handler = self
|
||||
|
||||
do {
|
||||
|
||||
try newFetchedResultsController.performFetchFromSpecifiedStores()
|
||||
}
|
||||
catch {
|
||||
|
||||
// DataStack may have been deallocated
|
||||
return
|
||||
}
|
||||
(self.fetchedResultsController, self.fetchedResultsControllerDelegate) = (newFetchedResultsController, newFetchedResultsControllerDelegate)
|
||||
}
|
||||
self.query = (
|
||||
from: from,
|
||||
sectionBy: sectionBy,
|
||||
sectionIndexTransformer: sectionBy?.sectionIndexTransformer ?? { $0 },
|
||||
applyFetchClauses: applyFetchClauses
|
||||
)
|
||||
(self.fetchedResultsController, self.fetchedResultsControllerDelegate) = (newFetchedResultsController, newFetchedResultsControllerDelegate)
|
||||
}
|
||||
|
||||
deinit {
|
||||
@@ -372,16 +307,19 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var query: (
|
||||
from: From<O>,
|
||||
sectionBy: SectionBy<O>?,
|
||||
sectionIndexTransformer: (_ sectionName: KeyPathString?) -> String?,
|
||||
applyFetchClauses: (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void
|
||||
)
|
||||
|
||||
private var fetchedResultsController: Internals.CoreStoreFetchedResultsController
|
||||
private var fetchedResultsControllerDelegate: Internals.FetchedDiffableDataSourceSnapshotDelegate
|
||||
private let sectionIndexTransformer: (_ sectionName: KeyPathString?) -> String?
|
||||
private var applyFetchClauses: (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void
|
||||
private var observerForWillChangePersistentStore: Internals.NotificationObserver!
|
||||
private var observerForDidChangePersistentStore: Internals.NotificationObserver!
|
||||
|
||||
private let from: From<ObjectType>
|
||||
private let sectionBy: SectionBy<ObjectType>?
|
||||
private lazy var observers: NSMapTable<AnyObject, Internals.Closure<LiveList<O>, Void>> = .weakToStrongObjects()
|
||||
private lazy var observers: NSMapTable<AnyObject, Internals.Closure<ListPublisher<O>, Void>> = .weakToStrongObjects()
|
||||
|
||||
private lazy var context: NSManagedObjectContext = self.fetchedResultsController.managedObjectContext
|
||||
|
||||
@@ -407,10 +345,14 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
return (fetchedResultsController, fetchedResultsControllerDelegate)
|
||||
}
|
||||
|
||||
private init(context: NSManagedObjectContext, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((LiveList<ObjectType>) -> Void)?) {
|
||||
private init(context: NSManagedObjectContext, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListPublisher<ObjectType>) -> Void)?) {
|
||||
|
||||
self.from = from
|
||||
self.sectionBy = sectionBy
|
||||
self.query = (
|
||||
from: from,
|
||||
sectionBy: sectionBy,
|
||||
sectionIndexTransformer: sectionBy?.sectionIndexTransformer ?? { $0 },
|
||||
applyFetchClauses: applyFetchClauses
|
||||
)
|
||||
(self.fetchedResultsController, self.fetchedResultsControllerDelegate) = Self.recreateFetchedResultsController(
|
||||
context: context,
|
||||
from: from,
|
||||
@@ -433,15 +375,6 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
self.rawObjectWillChange = nil
|
||||
}
|
||||
|
||||
if let sectionIndexTransformer = sectionBy?.sectionIndexTransformer {
|
||||
|
||||
self.sectionIndexTransformer = sectionIndexTransformer
|
||||
}
|
||||
else {
|
||||
|
||||
self.sectionIndexTransformer = { $0 }
|
||||
}
|
||||
self.applyFetchClauses = applyFetchClauses
|
||||
self.fetchedResultsControllerDelegate.handler = self
|
||||
|
||||
try! self.fetchedResultsController.performFetchFromSpecifiedStores()
|
||||
@@ -455,15 +388,15 @@ public final class LiveList<O: DynamicObject>: Hashable {
|
||||
}
|
||||
for closure in enumerator {
|
||||
|
||||
(closure as! Internals.Closure<LiveList<O>, Void>).invoke(with: self)
|
||||
(closure as! Internals.Closure<ListPublisher<O>, Void>).invoke(with: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - LiveList: FetchedDiffableDataSourceSnapshotHandler
|
||||
// MARK: - ListPublisher: FetchedDiffableDataSourceSnapshotHandler
|
||||
|
||||
extension LiveList: FetchedDiffableDataSourceSnapshotHandler {
|
||||
extension ListPublisher: FetchedDiffableDataSourceSnapshotHandler {
|
||||
|
||||
// MARK: FetchedDiffableDataSourceSnapshotHandler
|
||||
|
||||
@@ -486,7 +419,7 @@ extension LiveList: FetchedDiffableDataSourceSnapshotHandler {
|
||||
|
||||
internal func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String?) -> String? {
|
||||
|
||||
return self.sectionIndexTransformer(sectionName)
|
||||
return self.query.sectionIndexTransformer(sectionName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,13 +428,13 @@ extension LiveList: FetchedDiffableDataSourceSnapshotHandler {
|
||||
import Combine
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
extension LiveList: ObservableObject {}
|
||||
extension ListPublisher: ObservableObject {}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - LiveList: LiveResult
|
||||
// MARK: - ListPublisher
|
||||
|
||||
extension LiveList: LiveResult {
|
||||
extension ListPublisher {
|
||||
|
||||
// MARK: ObservableObject
|
||||
|
||||
@@ -515,7 +448,7 @@ extension LiveList: LiveResult {
|
||||
|
||||
#endif
|
||||
|
||||
public func willChange() {
|
||||
fileprivate func willChange() {
|
||||
|
||||
guard #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) else {
|
||||
|
||||
@@ -536,8 +469,8 @@ extension LiveList: LiveResult {
|
||||
#endif
|
||||
}
|
||||
|
||||
public func didChange() {
|
||||
fileprivate func didChange() {
|
||||
|
||||
// TODO:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
@@ -36,63 +36,174 @@ import AppKit
|
||||
|
||||
// MARK: - ListSnapshot
|
||||
|
||||
public struct ListSnapshot<O: DynamicObject>: SnapshotResult, RandomAccessCollection, Hashable {
|
||||
/**
|
||||
A `ListSnapshot` holds a stable list of `DynamicObject` identifiers. This is typically created by a `ListPublisher` and are designed to work well with `DiffableDataSource.TableView`s and `DiffableDataSource.CollectionView`s. For detailed examples, see the documentation on `DiffableDataSource.TableView` and `DiffableDataSource.CollectionView`.
|
||||
|
||||
// MARK: Public
|
||||
While the `ListSnapshot` stores only object identifiers, all accessors to its items return `ObjectPublisher`s, which are lazily created. For more details, see the documentation on `ListObject`.
|
||||
|
||||
Since `ListSnapshot` is a value type, you can freely modify its items.
|
||||
*/
|
||||
public struct ListSnapshot<O: DynamicObject>: RandomAccessCollection, Hashable {
|
||||
|
||||
// MARK: Public (Accessors)
|
||||
|
||||
/**
|
||||
The `DynamicObject` type associated with this list
|
||||
*/
|
||||
public typealias ObjectType = O
|
||||
|
||||
/**
|
||||
The type for the section IDs
|
||||
*/
|
||||
public typealias SectionID = String
|
||||
|
||||
/**
|
||||
The type for the item IDs
|
||||
*/
|
||||
public typealias ItemID = O.ObjectID
|
||||
|
||||
public init(byCloning snapshot: ListSnapshot<O>, for dataStack: DataStack) {
|
||||
|
||||
// if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
|
||||
//
|
||||
// self.init(
|
||||
// diffableSnapshot: snapshot.diffableSnapshot as! NSDiffableDataSourceSnapshot<String, NSManagedObjectID>,
|
||||
// context: dataStack.mainContext
|
||||
// )
|
||||
// }
|
||||
// else {
|
||||
/**
|
||||
Returns the object at the given index.
|
||||
|
||||
self.init(
|
||||
diffableSnapshot: snapshot.diffableSnapshot as! Internals.DiffableDataSourceSnapshot,
|
||||
context: dataStack.mainContext
|
||||
)
|
||||
// }
|
||||
- parameter index: the index of the object. Using an index above the valid range will raise an exception.
|
||||
- returns: the `ObjectPublisher<O>` interfacing the object at the specified index
|
||||
*/
|
||||
public subscript(index: Index) -> ObjectPublisher<O> {
|
||||
|
||||
let context = self.context!
|
||||
let itemID = self.diffableSnapshot.itemIdentifiers[index]
|
||||
return context.objectPublisher(objectID: itemID)
|
||||
}
|
||||
|
||||
public subscript<S: Sequence>(indices indices: S) -> [LiveObject<O>] where S.Element == Index {
|
||||
/**
|
||||
Returns the object at the given index, or `nil` if out of bounds.
|
||||
|
||||
- parameter index: the index for the object. Using an index above the valid range will return `nil`.
|
||||
- returns: the `ObjectPublisher<O>` interfacing the object at the specified index, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeIndex index: Index) -> ObjectPublisher<O>? {
|
||||
|
||||
let context = self.context!
|
||||
let itemIDs = self.diffableSnapshot.itemIdentifiers
|
||||
return indices.map { position in
|
||||
guard itemIDs.indices.contains(index) else {
|
||||
|
||||
let itemID = itemIDs[position]
|
||||
return LiveObject<O>(objectID: itemID, context: context)
|
||||
return nil
|
||||
}
|
||||
let itemID = itemIDs[index]
|
||||
return context.objectPublisher(objectID: itemID)
|
||||
}
|
||||
|
||||
public subscript(section sectionID: SectionID) -> [LiveObject<O>] {
|
||||
/**
|
||||
Returns the object at the given `sectionIndex` and `itemIndex`.
|
||||
|
||||
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will raise an exception.
|
||||
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will raise an exception.
|
||||
- returns: the `ObjectPublisher<O>` interfacing the object at the specified section and item index
|
||||
*/
|
||||
public subscript(sectionIndex: Int, itemIndex: Int) -> ObjectPublisher<O> {
|
||||
|
||||
let context = self.context!
|
||||
let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: sectionID)
|
||||
return itemIDs.map {
|
||||
|
||||
return LiveObject<O>(objectID: $0, context: context)
|
||||
}
|
||||
let snapshot = self.diffableSnapshot
|
||||
let sectionID = snapshot.sectionIdentifiers[sectionIndex]
|
||||
let itemID = snapshot.itemIdentifiers(inSection: sectionID)[itemIndex]
|
||||
return context.objectPublisher(objectID: itemID)
|
||||
}
|
||||
|
||||
public subscript<S: Sequence>(section sectionID: SectionID, itemIndices itemIndices: S) -> [LiveObject<O>] where S.Element == Int {
|
||||
/**
|
||||
Returns the object at the given section and item index, or `nil` if out of bounds.
|
||||
|
||||
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will return `nil`.
|
||||
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will return `nil`.
|
||||
- returns: the `ObjectPublisher<O>` interfacing the object at the specified section and item index, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeSectionIndex sectionIndex: Int, safeItemIndex itemIndex: Int) -> ObjectPublisher<O>? {
|
||||
|
||||
let context = self.context!
|
||||
let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: sectionID)
|
||||
return itemIndices.map { position in
|
||||
let snapshot = self.diffableSnapshot
|
||||
let sectionIDs = snapshot.sectionIdentifiers
|
||||
guard sectionIDs.indices.contains(sectionIndex) else {
|
||||
|
||||
let itemID = itemIDs[position]
|
||||
return LiveObject<O>(objectID: itemID, context: context)
|
||||
return nil
|
||||
}
|
||||
let sectionID = sectionIDs[sectionIndex]
|
||||
let itemIDs = snapshot.itemIdentifiers(inSection: sectionID)
|
||||
guard itemIDs.indices.contains(itemIndex) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
let itemID = itemIDs[itemIndex]
|
||||
return context.objectPublisher(objectID: itemID)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the object at the given `IndexPath`.
|
||||
|
||||
- parameter indexPath: the `IndexPath` for the object. Using an `indexPath` with an invalid range will raise an exception.
|
||||
- returns: the `ObjectPublisher<O>` interfacing the object at the specified index path
|
||||
*/
|
||||
public subscript(indexPath: IndexPath) -> ObjectPublisher<O> {
|
||||
|
||||
return self[indexPath[0], indexPath[1]]
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the object at the given `IndexPath`, or `nil` if out of bounds.
|
||||
|
||||
- parameter indexPath: the `IndexPath` for the object. Using an `indexPath` with an invalid range will return `nil`.
|
||||
- returns: the `ObjectPublisher<O>` interfacing the object at the specified index path, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeIndexPath indexPath: IndexPath) -> ObjectPublisher<O>? {
|
||||
|
||||
return self[
|
||||
safeSectionIndex: indexPath[0],
|
||||
safeItemIndex: indexPath[1]
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the `ListSnapshot` has at least one section
|
||||
|
||||
- returns: `true` if at least one section exists, `false` otherwise
|
||||
*/
|
||||
public func hasSections() -> Bool {
|
||||
|
||||
return self.diffableSnapshot.numberOfSections > 0
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the `ListSnapshot` has at least one object in any section.
|
||||
|
||||
- returns: `true` if at least one object in any section exists, `false` otherwise
|
||||
*/
|
||||
public func hasObjects() -> Bool {
|
||||
|
||||
return self.diffableSnapshot.numberOfItems > 0
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the `ListSnapshot` has at least one object the specified section.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `false`.
|
||||
- returns: `true` if at least one object in the specified section exists, `false` otherwise
|
||||
*/
|
||||
public func hasObjects(in sectionIndex: Int) -> Bool {
|
||||
|
||||
let snapshot = self.diffableSnapshot
|
||||
let sectionIDs = snapshot.sectionIdentifiers
|
||||
guard sectionIDs.indices.contains(sectionIndex) else {
|
||||
|
||||
return false
|
||||
}
|
||||
let sectionID = sectionIDs[sectionIndex]
|
||||
return snapshot.numberOfItems(inSection: sectionID) > 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public var numberOfItems: Int {
|
||||
|
||||
return self.diffableSnapshot.numberOfItems
|
||||
@@ -218,11 +329,39 @@ public struct ListSnapshot<O: DynamicObject>: SnapshotResult, RandomAccessCollec
|
||||
|
||||
self.diffableSnapshot.reloadSections(identifiers)
|
||||
}
|
||||
|
||||
|
||||
// MARK: SnapshotResult
|
||||
|
||||
public typealias ObjectType = O
|
||||
|
||||
public func items<S: Sequence>(atIndices indices: S) -> [ObjectPublisher<O>] where S.Element == Index {
|
||||
|
||||
let context = self.context!
|
||||
let itemIDs = self.diffableSnapshot.itemIdentifiers
|
||||
return indices.map { position in
|
||||
|
||||
let itemID = itemIDs[position]
|
||||
return ObjectPublisher<O>(objectID: itemID, context: context)
|
||||
}
|
||||
}
|
||||
|
||||
public subscript(section sectionID: SectionID) -> [ObjectPublisher<O>] {
|
||||
|
||||
let context = self.context!
|
||||
let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: sectionID)
|
||||
return itemIDs.map {
|
||||
|
||||
return ObjectPublisher<O>(objectID: $0, context: context)
|
||||
}
|
||||
}
|
||||
|
||||
public subscript<S: Sequence>(section sectionID: SectionID, itemIndices itemIndices: S) -> [ObjectPublisher<O>] where S.Element == Int {
|
||||
|
||||
let context = self.context!
|
||||
let itemIDs = self.diffableSnapshot.itemIdentifiers(inSection: sectionID)
|
||||
return itemIndices.map { position in
|
||||
|
||||
let itemID = itemIDs[position]
|
||||
return ObjectPublisher<O>(objectID: itemID, context: context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: RandomAccessCollection
|
||||
@@ -237,17 +376,10 @@ public struct ListSnapshot<O: DynamicObject>: SnapshotResult, RandomAccessCollec
|
||||
return self.diffableSnapshot.itemIdentifiers.endIndex
|
||||
}
|
||||
|
||||
public subscript(position: Index) -> Element {
|
||||
|
||||
let context = self.context!
|
||||
let itemID = self.diffableSnapshot.itemIdentifiers[position]
|
||||
return LiveObject<O>(objectID: itemID, context: context)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Sequence
|
||||
|
||||
public typealias Element = LiveObject<O>
|
||||
public typealias Element = ObjectPublisher<O>
|
||||
|
||||
public typealias Index = Int
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// File.swift
|
||||
// CoreStore iOS
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#if canImport(UIKit) || canImport(AppKit)
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
|
||||
#elseif canImport(AppKit)
|
||||
import AppKit
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - LiveResult
|
||||
|
||||
public protocol LiveResult: AnyObject {
|
||||
|
||||
associatedtype ObjectType
|
||||
associatedtype SnapshotType: SnapshotResult where SnapshotType.ObjectType == Self.ObjectType
|
||||
|
||||
func willChange()
|
||||
func didChange()
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -87,21 +87,21 @@ extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func liveObject<D: DynamicObject>(objectID: NSManagedObjectID) -> LiveObject<D> {
|
||||
internal func objectPublisher<D: DynamicObject>(objectID: NSManagedObjectID) -> ObjectPublisher<D> {
|
||||
|
||||
let cache: NSMapTable<NSManagedObjectID, LiveObject<D>> = self.userInfo(for: .liveObjectsCache(D.self)) {
|
||||
let cache: NSMapTable<NSManagedObjectID, ObjectPublisher<D>> = self.userInfo(for: .objectPublishersCache(D.self)) {
|
||||
|
||||
return .strongToWeakObjects()
|
||||
}
|
||||
return Internals.with {
|
||||
|
||||
if let liveObject = cache.object(forKey: objectID) {
|
||||
if let objectPublisher = cache.object(forKey: objectID) {
|
||||
|
||||
return liveObject
|
||||
return objectPublisher
|
||||
}
|
||||
let liveObject = LiveObject<D>(objectID: objectID, context: self)
|
||||
cache.setObject(liveObject, forKey: objectID)
|
||||
return liveObject
|
||||
let objectPublisher = ObjectPublisher<D>(objectID: objectID, context: self)
|
||||
cache.setObject(objectPublisher, forKey: objectID)
|
||||
return objectPublisher
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,15 +185,15 @@ extension NSManagedObjectContext {
|
||||
|
||||
private enum UserInfoKeys {
|
||||
|
||||
case liveObjectsCache(DynamicObject.Type)
|
||||
case objectPublishersCache(DynamicObject.Type)
|
||||
case objectsChangeObserver(AnyObject.Type)
|
||||
|
||||
var keyString: String {
|
||||
|
||||
switch self {
|
||||
|
||||
case .liveObjectsCache(let objectType):
|
||||
return "CoreStore.liveObjectsCache(\(Internals.typeName(objectType)))"
|
||||
case .objectPublishersCache(let objectType):
|
||||
return "CoreStore.objectPublishersCache(\(Internals.typeName(objectType)))"
|
||||
|
||||
case .objectsChangeObserver:
|
||||
return "CoreStore.objectsChangeObserver"
|
||||
|
||||
@@ -325,6 +325,12 @@ public final class ObjectMonitor<O: DynamicObject>: Equatable {
|
||||
inObject: observer
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// LiveObject.swift
|
||||
// ObjectPublisher.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
@@ -36,44 +36,89 @@ import SwiftUI
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - LiveObject
|
||||
// MARK: - ObjectPublisher
|
||||
|
||||
/**
|
||||
The `ObjectPublisher` tracks changes to a single `DynamicObject` instance. Objects that need to be notified of `ObjectPublisher` changes may register themselves to its `addObserver(_:_:)` method:
|
||||
```
|
||||
let objectPublisher = Shared.defaultStack.objectPublisher(object)
|
||||
objectPublisher.addObserver(self) { (objectPublisher) in
|
||||
// Handle changes
|
||||
}
|
||||
```
|
||||
The created `ObjectPublisher` instance needs to be held on (retained) for as long as the object needs to be observed.
|
||||
|
||||
Observers registered via `addObserver(_:_:)` are not retained. `ObjectPublisher` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
|
||||
|
||||
The `ObjectPublisher`'s `snapshot` value is a lazy copy operation that extracts all property values at a specific point time. This cached copy is invalidated right before the `ObjectPublisher` broadcasts any changes to its observers.
|
||||
*/
|
||||
@dynamicMemberLookup
|
||||
public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
public typealias SectionID = String
|
||||
public typealias ItemID = O.ObjectID
|
||||
public final class ObjectPublisher<O: DynamicObject>: ObjectRepresentation, Hashable {
|
||||
|
||||
// MARK: Public (Accessors)
|
||||
/**
|
||||
A snapshot of the latest state of this list. Returns `nil` if the object has been deleted.
|
||||
*/
|
||||
public var snapshot: ObjectSnapshot<O>? {
|
||||
|
||||
return self.lazySnapshot
|
||||
}
|
||||
|
||||
public lazy var object: O? = self.context.fetchExisting(self.id)
|
||||
|
||||
public func addObserver<T: AnyObject>(_ observer: T, _ callback: @escaping (LiveObject<O>) -> Void) {
|
||||
|
||||
/**
|
||||
The actual `DynamicObject` instance. Becomes `nil` if the object has been deleted.
|
||||
*/
|
||||
public private(set) lazy var object: O? = self.context.fetchExisting(self.id)
|
||||
|
||||
|
||||
|
||||
// MARK: Public (Observers)
|
||||
|
||||
/**
|
||||
Registers an object as an observer to be notified when changes to the `ObjectPublisher`'s snapshot occur.
|
||||
|
||||
To prevent retain-cycles, `ObjectPublisher` only keeps `weak` references to its observers.
|
||||
|
||||
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
|
||||
|
||||
Calling `addObserver(_:_:)` multiple times on the same observer is safe.
|
||||
|
||||
- parameter observer: an object to become owner of the specified `callback`
|
||||
- parameter callback: the closure to execute when changes occur
|
||||
*/
|
||||
public func addObserver<T: AnyObject>(_ observer: T, _ callback: @escaping (ObjectPublisher<O>) -> Void) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to add an observer of type \(Internals.typeName(observer)) outside the main thread."
|
||||
)
|
||||
self.observers.setObject(
|
||||
Internals.Closure(callback),
|
||||
forKey: observer
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Unregisters an object from receiving notifications for changes to the `ObjectPublisher`'s snapshot.
|
||||
|
||||
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
|
||||
|
||||
- parameter observer: the object whose notifications will be unregistered
|
||||
*/
|
||||
public func removeObserver<T: AnyObject>(_ observer: T) {
|
||||
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to remove an observer of type \(Internals.typeName(observer)) outside the main thread."
|
||||
)
|
||||
self.observers.removeObject(forKey: observer)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.observers.removeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
// MARK: ObjectRepresentation
|
||||
|
||||
/**
|
||||
The `DynamicObject` type associated with this list
|
||||
*/
|
||||
public typealias ObjectType = O
|
||||
|
||||
public func objectID() -> O.ObjectID {
|
||||
@@ -81,7 +126,7 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
return self.id
|
||||
}
|
||||
|
||||
public func asLiveObject(in dataStack: DataStack) -> LiveObject<O> {
|
||||
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
if self.context == context {
|
||||
@@ -124,7 +169,7 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == (_ lhs: LiveObject, _ rhs: LiveObject) -> Bool {
|
||||
public static func == (_ lhs: ObjectPublisher, _ rhs: ObjectPublisher) -> Bool {
|
||||
|
||||
return lhs.id == rhs.id
|
||||
&& lhs.context == rhs.context
|
||||
@@ -140,11 +185,6 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
}
|
||||
|
||||
|
||||
// MARK: LiveResult
|
||||
|
||||
public typealias SnapshotType = ObjectSnapshot<O>
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal convenience init(objectID: O.ObjectID, context: NSManagedObjectContext) {
|
||||
@@ -156,6 +196,11 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.observers.removeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
@@ -193,15 +238,15 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
|
||||
self.willChange()
|
||||
self.$lazySnapshot.reset({ nil })
|
||||
self.notifyObservers()
|
||||
self.didChange()
|
||||
self.notifyObservers()
|
||||
}
|
||||
else if updatedIDs.contains(objectID) {
|
||||
|
||||
self.willChange()
|
||||
self.$lazySnapshot.reset({ initializer(objectID, context) })
|
||||
self.notifyObservers()
|
||||
self.didChange()
|
||||
self.notifyObservers()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +260,7 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
@Internals.LazyNonmutating(uninitialized: ())
|
||||
private var lazySnapshot: ObjectSnapshot<O>?
|
||||
|
||||
private lazy var observers: NSMapTable<AnyObject, Internals.Closure<LiveObject<O>, Void>> = .weakToStrongObjects()
|
||||
private lazy var observers: NSMapTable<AnyObject, Internals.Closure<ObjectPublisher<O>, Void>> = .weakToStrongObjects()
|
||||
|
||||
private func notifyObservers() {
|
||||
|
||||
@@ -225,7 +270,7 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
}
|
||||
for closure in enumerator {
|
||||
|
||||
(closure as! Internals.Closure<LiveObject
|
||||
(closure as! Internals.Closure<ObjectPublisher
|
||||
<O>, Void>).invoke(with: self)
|
||||
}
|
||||
}
|
||||
@@ -236,13 +281,13 @@ public final class LiveObject<O: DynamicObject>: ObjectRepresentation, Hashable
|
||||
import Combine
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
extension LiveObject: ObservableObject {}
|
||||
extension ObjectPublisher: ObservableObject {}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - LiveObject: LiveResult
|
||||
// MARK: - ObjectPublisher
|
||||
|
||||
extension LiveObject: LiveResult {
|
||||
extension ObjectPublisher {
|
||||
|
||||
// MARK: ObservableObject
|
||||
|
||||
@@ -256,7 +301,7 @@ extension LiveObject: LiveResult {
|
||||
|
||||
#endif
|
||||
|
||||
public func willChange() {
|
||||
fileprivate func willChange() {
|
||||
|
||||
guard #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) else {
|
||||
|
||||
@@ -277,17 +322,17 @@ extension LiveObject: LiveResult {
|
||||
#endif
|
||||
}
|
||||
|
||||
public func didChange() {
|
||||
fileprivate func didChange() {
|
||||
|
||||
// TODO:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - LiveObject where O: NSManagedObject
|
||||
// MARK: - ObjectPublisher where O: NSManagedObject
|
||||
|
||||
@available(*, unavailable, message: "KeyPaths accessed from @dynamicMemberLookup types can't generate KVC keys yet (https://bugs.swift.org/browse/SR-11351)")
|
||||
extension LiveObject where O: NSManagedObject {
|
||||
extension ObjectPublisher where O: NSManagedObject {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -302,9 +347,9 @@ extension LiveObject where O: NSManagedObject {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - LiveObject where O: CoreStoreObject
|
||||
// MARK: - ObjectPublisher where O: CoreStoreObject
|
||||
|
||||
extension LiveObject where O: CoreStoreObject {
|
||||
extension ObjectPublisher where O: CoreStoreObject {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -46,7 +46,7 @@ public protocol ObjectRepresentation {
|
||||
/**
|
||||
An instance that may be observed for object changes.
|
||||
*/
|
||||
func asLiveObject(in dataStack: DataStack) -> LiveObject<ObjectType>
|
||||
func asPublisher(in dataStack: DataStack) -> ObjectPublisher<ObjectType>
|
||||
|
||||
/**
|
||||
A read-only instance in the `DataStack`.
|
||||
@@ -82,10 +82,10 @@ extension DynamicObject where Self: ObjectRepresentation {
|
||||
return self.cs_id()
|
||||
}
|
||||
|
||||
public func asLiveObject(in dataStack: DataStack) -> LiveObject<Self> {
|
||||
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<Self> {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
return LiveObject<Self>(objectID: self.cs_id(), context: context)
|
||||
return ObjectPublisher<Self>(objectID: self.cs_id(), context: context)
|
||||
}
|
||||
|
||||
public func asReadOnly(in dataStack: DataStack) -> Self? {
|
||||
|
||||
@@ -37,9 +37,7 @@ import AppKit
|
||||
// MARK: - ObjectSnapshot
|
||||
|
||||
@dynamicMemberLookup
|
||||
public struct ObjectSnapshot<O: DynamicObject>: SnapshotResult, ObjectRepresentation, Hashable {
|
||||
|
||||
// MARK: SnapshotResult
|
||||
public struct ObjectSnapshot<O: DynamicObject>: ObjectRepresentation, Hashable {
|
||||
|
||||
public typealias ObjectType = O
|
||||
|
||||
@@ -51,10 +49,10 @@ public struct ObjectSnapshot<O: DynamicObject>: SnapshotResult, ObjectRepresenta
|
||||
return self.id
|
||||
}
|
||||
|
||||
public func asLiveObject(in dataStack: DataStack) -> LiveObject<O> {
|
||||
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> {
|
||||
|
||||
let context = dataStack.unsafeContext()
|
||||
return LiveObject<O>(objectID: self.id, context: context)
|
||||
return ObjectPublisher<O>(objectID: self.id, context: context)
|
||||
}
|
||||
|
||||
public func asReadOnly(in dataStack: DataStack) -> O? {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// SnapshotResult.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2018 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#if canImport(UIKit) || canImport(AppKit)
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
|
||||
#elseif canImport(AppKit)
|
||||
import AppKit
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - SnapshotResult
|
||||
|
||||
public protocol SnapshotResult {
|
||||
|
||||
associatedtype ObjectType: DynamicObject
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user