From b073b7e795330a342d832a7afef16d9ee56df8ab Mon Sep 17 00:00:00 2001 From: John Estropia Date: Sun, 6 Oct 2019 23:37:04 +0900 Subject: [PATCH] swiftUI support done for now --- CoreStore.xcodeproj/project.pbxproj | 75 ++++++- .../CoreStoreDemo.xcodeproj/project.pbxproj | 16 +- .../CoreStoreDemo/Base.lproj/Main.storyboard | 188 +++++++----------- .../CoreStoreDemo/MenuViewController.swift | 92 --------- .../SwiftUIContainerViewController.swift | 47 +++++ .../SwiftUIHostingController.swift | 31 --- .../SwiftUI Demo/SwiftUIView.swift | 88 ++++---- Sources/EnvironmentKeys.swift | 45 +++++ Sources/ListSnapshot.swift | 131 ++++++++++++ Sources/LiveList.swift | 164 +++------------ Sources/LiveQuery.swift | 165 +++++++++++++++ Sources/LiveResult.swift | 46 +++++ Sources/Shared.swift | 1 - Sources/SnapshotResult.swift | 45 +++++ 14 files changed, 710 insertions(+), 424 deletions(-) delete mode 100644 CoreStoreDemo/CoreStoreDemo/MenuViewController.swift create mode 100644 CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIContainerViewController.swift delete mode 100644 CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIHostingController.swift create mode 100644 Sources/EnvironmentKeys.swift create mode 100644 Sources/ListSnapshot.swift create mode 100644 Sources/LiveQuery.swift create mode 100644 Sources/LiveResult.swift create mode 100644 Sources/SnapshotResult.swift diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 31f6205..de467fc 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -78,6 +78,12 @@ 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 */; }; B50132332346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501322F2346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift */; }; + B501323723477F9300FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323623477F9300FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B501323923477FAC00FC238B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323823477FAC00FC238B /* UIKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B501323D23477FD500FC238B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323C23477FD500FC238B /* UIKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B501323F23477FE800FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323E23477FE800FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B501324023477FF800FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323623477F9300FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B50132412347800000FC238B /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323A23477FB600FC238B /* AppKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; B501FDDD1CA8D05000BE22EF /* CSSectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */; }; B501FDDF1CA8D05000BE22EF /* CSSectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */; }; B501FDE01CA8D05000BE22EF /* CSSectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */; }; @@ -640,6 +646,10 @@ 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 */; }; @@ -736,6 +746,22 @@ 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 */; }; + B5F3355C2348D93700FD649F /* LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F84966234887EB0029D57B /* LiveQuery.swift */; }; + B5F3355D2348D93800FD649F /* LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F84966234887EB0029D57B /* LiveQuery.swift */; }; + B5F3355E2348D93900FD649F /* LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F84966234887EB0029D57B /* LiveQuery.swift */; }; + B5F3355F2348D93900FD649F /* LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F84966234887EB0029D57B /* LiveQuery.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 */; }; + B5F8496F234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; }; + B5F849712348A6690029D57B /* EnvironmentKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F849702348A6690029D57B /* EnvironmentKeys.swift */; }; + B5F849722348A6690029D57B /* EnvironmentKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F849702348A6690029D57B /* EnvironmentKeys.swift */; }; + B5F849732348A6690029D57B /* EnvironmentKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F849702348A6690029D57B /* EnvironmentKeys.swift */; }; + B5F849742348A6690029D57B /* EnvironmentKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F849702348A6690029D57B /* EnvironmentKeys.swift */; }; B5FAD6A91B50A4B400714891 /* Progress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */; }; B5FAD6AC1B51285300714891 /* Internals.MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* Internals.MigrationManager.swift */; }; B5FAD6AE1B518DCB00714891 /* CoreStore+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */; }; @@ -796,6 +822,11 @@ 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 = ""; }; B501322F2346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.FetchedDiffableDataSourceSnapshotDelegate.swift; sourceTree = ""; }; + 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; }; + B501323A23477FB600FC238B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = DEVELOPER_DIR; }; + B501323C23477FD500FC238B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS13.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + B501323E23477FE800FC238B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS13.0.sdk/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; }; B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSectionBy.swift; sourceTree = ""; }; B501FDE11CA8D1F500BE22EF /* CSListMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSListMonitor.swift; sourceTree = ""; }; B501FDE61CA8D20500BE22EF /* CSListObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSListObserver.swift; sourceTree = ""; }; @@ -949,6 +980,7 @@ B5E1B5A71CAA49E2007FD580 /* CSDataStack+Migrating.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSDataStack+Migrating.swift"; sourceTree = ""; }; B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSynchronousDataTransaction.swift; sourceTree = ""; }; B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSUnsafeDataTransaction.swift; sourceTree = ""; }; + B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotResult.swift; sourceTree = ""; }; B5E41EBF1EA9BB37006240F0 /* DynamicSchema+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DynamicSchema+Convenience.swift"; sourceTree = ""; }; B5E5FA4D22D162F400330931 /* ObjectSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectSnapshot.swift; sourceTree = ""; }; B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BaseDataTransaction+Importing.swift"; sourceTree = ""; }; @@ -1002,6 +1034,10 @@ B5ECDC2E1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Transaction.swift"; sourceTree = ""; }; B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableObject.swift; sourceTree = ""; }; B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableUniqueObject.swift; sourceTree = ""; }; + B5F335572348D75D00FD649F /* LiveResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveResult.swift; sourceTree = ""; }; + B5F84966234887EB0029D57B /* LiveQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveQuery.swift; sourceTree = ""; }; + B5F8496B234898240029D57B /* ListSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSnapshot.swift; sourceTree = ""; }; + B5F849702348A6690029D57B /* EnvironmentKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentKeys.swift; sourceTree = ""; }; B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Progress+Convenience.swift"; sourceTree = ""; }; B5FAD6AB1B51285300714891 /* Internals.MigrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Internals.MigrationManager.swift; sourceTree = ""; }; B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "CoreStore+Migration.swift"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; @@ -1016,6 +1052,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B501323923477FAC00FC238B /* UIKit.framework in Frameworks */, + B501323723477F9300FC238B /* SwiftUI.framework in Frameworks */, B5D39A0219FD00C9000E91BB /* Foundation.framework in Frameworks */, 2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */, ); @@ -1033,6 +1071,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B501323F23477FE800FC238B /* SwiftUI.framework in Frameworks */, + B501323D23477FD500FC238B /* UIKit.framework in Frameworks */, B56507961D3930C1000596DA /* Foundation.framework in Frameworks */, B56507941D3930BC000596DA /* CoreData.framework in Frameworks */, ); @@ -1050,6 +1090,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B50132412347800000FC238B /* AppKit.framework in Frameworks */, + B501324023477FF800FC238B /* SwiftUI.framework in Frameworks */, B56507A01D3930F5000596DA /* Foundation.framework in Frameworks */, B565079E1D3930ED000596DA /* CoreData.framework in Frameworks */, ); @@ -1175,6 +1217,11 @@ 2F291E3119C6D4D3007AF63F /* Frameworks */ = { isa = PBXGroup; children = ( + B501323E23477FE800FC238B /* SwiftUI.framework */, + B501323C23477FD500FC238B /* UIKit.framework */, + B501323A23477FB600FC238B /* AppKit.framework */, + B501323823477FAC00FC238B /* UIKit.framework */, + B501323623477F9300FC238B /* SwiftUI.framework */, B565079F1D3930F5000596DA /* Foundation.framework */, B565079D1D3930ED000596DA /* CoreData.framework */, B56507991D3930D1000596DA /* Foundation.framework */, @@ -1457,10 +1504,15 @@ B5E5FA4C22D15D3C00330931 /* DataSources */ = { isa = PBXGroup; children = ( + B5F849702348A6690029D57B /* EnvironmentKeys.swift */, + B5F84966234887EB0029D57B /* LiveQuery.swift */, B50132292344ECB500FC238B /* LiveList.swift */, + B5F8496B234898240029D57B /* ListSnapshot.swift */, B50EE14123473C92009B8C47 /* CoreStoreObject+DataSources.swift */, B5E5FA4D22D162F400330931 /* ObjectSnapshot.swift */, B5D8CA752346E7590055D7D1 /* DataStack+DataSources.swift */, + B5F335572348D75D00FD649F /* LiveResult.swift */, + B5E294DC2349F8E7003E5956 /* SnapshotResult.swift */, ); name = DataSources; sourceTree = ""; @@ -1950,7 +2002,6 @@ B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */, B5ECDC051CA8138100C7F112 /* CSOrderBy.swift in Sources */, B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, - B501322A2344ECB500FC238B /* LiveList.swift in Sources */, B5DAFB4A2203E01D003FCCD0 /* KeyPathGenericBindings.swift in Sources */, B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */, @@ -1961,6 +2012,7 @@ 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 */, @@ -1977,6 +2029,7 @@ B50132302346B76E00FC238B /* Internals.FetchedDiffableDataSourceSnapshotDelegate.swift in Sources */, B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */, B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */, + B5F849712348A6690029D57B /* EnvironmentKeys.swift in Sources */, B5E1B59D1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, B5ECDC231CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */, B549F6731E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, @@ -1985,6 +2038,7 @@ B5E1B5931CAA0C15007FD580 /* CSObjectMonitor.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 */, B5E84F361AFF85470064E85B /* NSManagedObjectContext+Setup.swift in Sources */, @@ -2094,6 +2148,9 @@ B5ECDC0B1CA8161B00C7F112 /* CSGroupBy.swift in Sources */, B5E84F151AFF847B0064E85B /* CoreStore+Querying.swift in Sources */, B5E84F241AFF84860064E85B /* ListObserver.swift in Sources */, + B501322A2344ECB500FC238B /* LiveList.swift in Sources */, + B5F3355C2348D93700FD649F /* LiveQuery.swift in Sources */, + B5F8496C234898240029D57B /* ListSnapshot.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2168,6 +2225,7 @@ 82BA18A51C4BBD2200A0916E /* CoreStore+Setup.swift in Sources */, 82BA18BD1C4BBD4A00A0916E /* GroupBy.swift in Sources */, B5ECDC1F1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, + B5E294DE2349F8E7003E5956 /* SnapshotResult.swift in Sources */, B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, @@ -2195,6 +2253,7 @@ B5831F432212700400D8604C /* Where.Expression.swift in Sources */, B51260941E9B28F100402229 /* Internals.EntityIdentifier.swift in Sources */, B5FE4DA81C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, + B5F8496D234898240029D57B /* ListSnapshot.swift in Sources */, B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */, 82BA18B41C4BBD3900A0916E /* BaseDataTransaction+Importing.swift in Sources */, @@ -2212,6 +2271,7 @@ B5E41EC11EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */, B501FDE41CA8D1F500BE22EF /* CSListMonitor.swift in Sources */, B5A1DAC91F111BFA003CF369 /* KeyPath+Querying.swift in Sources */, + B5F3355D2348D93800FD649F /* LiveQuery.swift in Sources */, B5FE4DA31C8481E100FA6A91 /* StorageInterface.swift in Sources */, B5ECDC131CA816E500C7F112 /* CSTweak.swift in Sources */, B56923C51EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */, @@ -2255,6 +2315,7 @@ B5D33A021E96012400C880DE /* Relationship.swift in Sources */, B559CD4B1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, B56923CA1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */, + B5F849722348A6690029D57B /* EnvironmentKeys.swift in Sources */, B56923E51EB827F5007C4DC9 /* CustomSchemaMappingProvider.swift in Sources */, B58D0C641EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */, B533C4DC1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */, @@ -2263,6 +2324,7 @@ 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 */, B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */, B51260801E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */, @@ -2371,6 +2433,7 @@ B546F95B1C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */, B52DD1A11BE1F92C00949AFE /* DataStack+Transaction.swift in Sources */, B5220E1C1D130801009BC71E /* Internals.FetchedResultsControllerDelegate.swift in Sources */, + B5E294E02349F8E7003E5956 /* SnapshotResult.swift in Sources */, B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */, B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */, @@ -2398,6 +2461,7 @@ B53CA9A51EF1EF1600E0F440 /* PartialObject.swift in Sources */, B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */, B53FBA1C1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */, + B5F8496F234898240029D57B /* ListSnapshot.swift in Sources */, B5831F452212700500D8604C /* Where.Expression.swift in Sources */, B51260961E9B28F100402229 /* Internals.EntityIdentifier.swift in Sources */, B5ECDBE31CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */, @@ -2415,6 +2479,7 @@ B5220E131D1305ED009BC71E /* SectionBy.swift in Sources */, B559CD4D1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, B5E41EC31EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */, + B5F3355F2348D93900FD649F /* LiveQuery.swift in Sources */, B5ECDBE91CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */, B5A1DACB1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */, B52DD1B81BE1F94000949AFE /* DataStack+Migration.swift in Sources */, @@ -2458,6 +2523,7 @@ B56923CC1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */, B56923E71EB827F5007C4DC9 /* CustomSchemaMappingProvider.swift in Sources */, B58D0C661EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */, + B5F849742348A6690029D57B /* EnvironmentKeys.swift in Sources */, B533C4DE1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */, B5220E141D130614009BC71E /* DataStack+Observing.swift in Sources */, B52DD1A21BE1F92C00949AFE /* CoreStore+Transaction.swift in Sources */, @@ -2466,6 +2532,7 @@ 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 */, B51260821E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */, B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */, @@ -2574,6 +2641,7 @@ B56321831BD65216006C9394 /* CoreStore+Setup.swift in Sources */, B5ECDC201CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, + B5E294DF2349F8E7003E5956 /* SnapshotResult.swift in Sources */, B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, @@ -2601,6 +2669,7 @@ B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */, B5FE4DA91C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B5831F442212700500D8604C /* Where.Expression.swift in Sources */, + B5F8496E234898240029D57B /* ListSnapshot.swift in Sources */, B51260951E9B28F100402229 /* Internals.EntityIdentifier.swift in Sources */, B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */, @@ -2618,6 +2687,7 @@ B501FDEA1CA8D20500BE22EF /* CSListObserver.swift in Sources */, B501FDE51CA8D1F500BE22EF /* CSListMonitor.swift in Sources */, B5E41EC21EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */, + B5F3355E2348D93900FD649F /* LiveQuery.swift in Sources */, B5ECDC141CA816E500C7F112 /* CSTweak.swift in Sources */, B5A1DACA1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */, B56321AE1BD6521C006C9394 /* Internals.NotificationObserver.swift in Sources */, @@ -2661,6 +2731,7 @@ B5215CA61FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */, B5D33A031E96012400C880DE /* Relationship.swift in Sources */, B559CD4C1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, + B5F849732348A6690029D57B /* EnvironmentKeys.swift in Sources */, B56923CB1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */, B56923E61EB827F5007C4DC9 /* CustomSchemaMappingProvider.swift in Sources */, B58D0C651EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */, @@ -2669,6 +2740,7 @@ 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 */, B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */, B51260811E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */, @@ -2786,6 +2858,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore; PRODUCT_NAME = CoreStore; SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = singlefile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 5.0; diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj index ac94d63..7c77eea 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj @@ -8,8 +8,8 @@ /* Begin PBXBuildFile section */ B50132242344E24300FC238B /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132232344E24300FC238B /* SwiftUIView.swift */; }; - B50132262344E44B00FC238B /* MenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132252344E44B00FC238B /* MenuViewController.swift */; }; - B50132282344E5E900FC238B /* SwiftUIHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132272344E5E900FC238B /* SwiftUIHostingController.swift */; }; + B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */; }; + B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323423477D2300FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */; }; B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */; }; B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; }; @@ -63,8 +63,8 @@ /* Begin PBXFileReference section */ B50132232344E24300FC238B /* SwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIView.swift; sourceTree = ""; }; - B50132252344E44B00FC238B /* MenuViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuViewController.swift; sourceTree = ""; }; - B50132272344E5E900FC238B /* SwiftUIHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIHostingController.swift; sourceTree = ""; }; + B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIContainerViewController.swift; sourceTree = ""; }; + B501323423477D2300FC238B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListObserverDemoViewController.swift; sourceTree = ""; }; B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverDemoViewController.swift; sourceTree = ""; }; B503FADD1AFDC71700F90881 /* Palette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palette.swift; sourceTree = ""; }; @@ -111,6 +111,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */, B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */, B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */, B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */, @@ -124,7 +125,7 @@ isa = PBXGroup; children = ( B50132232344E24300FC238B /* SwiftUIView.swift */, - B50132272344E5E900FC238B /* SwiftUIHostingController.swift */, + B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */, ); path = "SwiftUI Demo"; sourceTree = ""; @@ -153,6 +154,7 @@ B52977E21B120F90003D50A5 /* Frameworks */ = { isa = PBXGroup; children = ( + B501323423477D2300FC238B /* SwiftUI.framework */, B52977E01B120F8A003D50A5 /* CoreLocation.framework */, B5BDC9211C202429008147CD /* CoreStore.framework */, B52977DE1B120F83003D50A5 /* MapKit.framework */, @@ -181,7 +183,6 @@ isa = PBXGroup; children = ( B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */, - B50132252344E44B00FC238B /* MenuViewController.swift */, B50132222344E20B00FC238B /* SwiftUI Demo */, B566E3271B117AE700F4F0C6 /* Stack Setup Demo */, B503FADA1AFDC71700F90881 /* List and Object Observers Demo */, @@ -328,7 +329,6 @@ buildActionMask = 2147483647; files = ( B56965181B2E20CC0075EE4A /* TimeZone.swift in Sources */, - B50132262344E44B00FC238B /* MenuViewController.swift in Sources */, B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */, B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */, B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */, @@ -350,7 +350,7 @@ B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */, B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */, B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */, - B50132282344E5E900FC238B /* SwiftUIHostingController.swift in Sources */, + B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */, B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */, B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */, B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */, diff --git a/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard b/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard index 3a6c376..9779183 100644 --- a/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard +++ b/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard @@ -452,7 +452,7 @@ - + @@ -470,14 +470,36 @@ - + - - - - + + + + + + + + + + + + + + + + + + + + + - + @@ -488,18 +510,18 @@ - + - + - + - + - + @@ -624,19 +646,19 @@ - + - + - - - - + + + + @@ -678,7 +700,7 @@ - + @@ -733,92 +755,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -940,6 +876,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1120,7 +1087,4 @@ - - - diff --git a/CoreStoreDemo/CoreStoreDemo/MenuViewController.swift b/CoreStoreDemo/CoreStoreDemo/MenuViewController.swift deleted file mode 100644 index 1d07f24..0000000 --- a/CoreStoreDemo/CoreStoreDemo/MenuViewController.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// MenuViewController.swift -// CoreStoreDemo -// -// Created by John Rommel Estropia on 2019/10/02. -// Copyright © 2019 John Rommel Estropia. All rights reserved. -// - -import UIKit - -// MARK: - MenuViewController - -final class MenuViewController: UITableViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Uncomment the following line to preserve selection between presentations - // self.clearsSelectionOnViewWillAppear = false - - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem - } - - // MARK: - Table view data source - - override func numberOfSections(in tableView: UITableView) -> Int { - // #warning Incomplete implementation, return the number of sections - return 0 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - // #warning Incomplete implementation, return the number of rows - return 0 - } - - /* - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) - - // Configure the cell... - - return cell - } - */ - - /* - // Override to support conditional editing of the table view. - override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the specified item to be editable. - return true - } - */ - - /* - // Override to support editing the table view. - override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - // Delete the row from the data source - tableView.deleteRows(at: [indexPath], with: .fade) - } else if editingStyle == .insert { - // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view - } - } - */ - - /* - // Override to support rearranging the table view. - override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { - - } - */ - - /* - // Override to support conditional rearranging of the table view. - override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the item to be re-orderable. - return true - } - */ - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - -} diff --git a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIContainerViewController.swift b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIContainerViewController.swift new file mode 100644 index 0000000..449fdf6 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIContainerViewController.swift @@ -0,0 +1,47 @@ +// +// SwiftUIContainerViewController.swift +// CoreStoreDemo +// +// Created by John Rommel Estropia on 2019/10/02. +// Copyright © 2019 John Rommel Estropia. All rights reserved. +// + +import UIKit +import CoreStore + +#if canImport(SwiftUI) +import SwiftUI + +#endif + +final class SwiftUIContainerViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + #if canImport(SwiftUI) + + if #available(iOS 13, *) { + + let hostingController = UIHostingController( + rootView: SwiftUIView( + palettes: ColorsDemo.stack.liveList( + From() + .sectionBy(\.colorName) + .orderBy(.ascending(\.hue)) + ) + ) + .environment(\.dataStack, ColorsDemo.stack) + ) + self.addChild(hostingController) + + hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + hostingController.view.frame = self.view.bounds.inset(by: self.view.safeAreaInsets) + self.view.addSubview(hostingController.view) + + hostingController.didMove(toParent: self) + } + + #endif + } +} diff --git a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIHostingController.swift b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIHostingController.swift deleted file mode 100644 index 57a83e5..0000000 --- a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIHostingController.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// SwiftUIHostingController.swift -// CoreStoreDemo -// -// Created by John Rommel Estropia on 2019/10/02. -// Copyright © 2019 John Rommel Estropia. All rights reserved. -// - -#if canImport(SwiftUI) - -import SwiftUI -import UIKit -import CoreStore - -@available(iOS 13.0.0, *) -class SwiftUIHostingController: UIHostingController { - - @objc required dynamic init?(coder aDecoder: NSCoder) { - super.init( - coder: aDecoder, - rootView: SwiftUIView( - palettes: DataStackEnvironment.defaultValue.liveList( - From() - .orderBy(.ascending(\.hue)) - ) - ) - ) - } -} - -#endif diff --git a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift index 68178ff..bd12f94 100644 --- a/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift +++ b/CoreStoreDemo/CoreStoreDemo/SwiftUI Demo/SwiftUIView.swift @@ -11,58 +11,45 @@ import SwiftUI import CoreStore -@available(iOS 13.0, *) -struct DataStackEnvironment: EnvironmentKey { - - static let defaultValue = ColorsDemo.stack -} - - -@available(iOS 13.0.0, *) -extension EnvironmentValues { - - var dataStack: DataStack { - get { - return self[DataStackEnvironment.self] - } - set { - self[DataStackEnvironment.self] = newValue - } - } -} - @available(iOS 13.0.0, *) struct SwiftUIView: View { - @Environment(\.dataStack) var dataStack: DataStack + @Environment(\.dataStack) + var dataStack: DataStack - @ObservedObject var palettes: LiveList + @ObservedObject + var palettes: LiveList + + @State + private var needsShowAlert = false var body: some View { NavigationView { List { ForEach(palettes.snapshot, id: \.self) { palette in NavigationLink( - destination: DetailView(palette: palette) - ) { - HStack { - Color(palette.color) - .frame(width: 30, height: 30, alignment: .leading) - Text(palette.colorText) + destination: DetailView(palette: palette), + label: { + HStack { + Color(palette.color) + .frame(width: 30, height: 30, alignment: .leading) + Text(palette.colorText) + } } - } - }.onDelete { indices in + ) + } + .onDelete { indices in let palettes = self.palettes.snapshot[indices] self.dataStack.perform( asynchronous: { transaction in - palettes.forEach(transaction.delete(_:)) + transaction.delete(palettes) }, completion: { _ in } ) } } - .navigationBarTitle(Text("Master")) + .navigationBarTitle(Text("SwiftUI")) .navigationBarItems( leading: EditButton(), trailing: Button( @@ -76,38 +63,59 @@ struct SwiftUIView: View { }, completion: { _ in } ) - } - ) { - Image(systemName: "plus") + }, + label: { + Image(systemName: "plus") + } + ) + ) + .alert( + isPresented: $needsShowAlert, + content: { + Alert( + title: Text("SwiftUI Binding Demo"), + message: Text("This demo shows how to bind to LiveList and to CoreStoreObject when using SwiftUI"), + dismissButton: .cancel(Text("OK")) + ) } ) + .onAppear { + + self.needsShowAlert = true + } } + .colorScheme(.dark) } } @available(iOS 13.0.0, *) struct DetailView: View { + @ObservedObject var palette: Palette var body: some View { - HStack { - EmptyView() - .foregroundColor(.init(palette.color)) + ZStack { + Color(palette.color) + .cornerRadius(20) + .padding(20) Text(palette.colorText) - .navigationBarTitle(Text("Detail")) + .navigationBarTitle(Text("Color")) } } } @available(iOS 13.0.0, *) struct SwiftUIView_Previews: PreviewProvider { + static var previews: some View { SwiftUIView( - palettes: DataStackEnvironment.defaultValue.liveList( + palettes: ColorsDemo.stack.liveList( From() + .sectionBy(\.colorName) .orderBy(.ascending(\.hue)) ) ) + .environment(\.dataStack, ColorsDemo.stack) } } diff --git a/Sources/EnvironmentKeys.swift b/Sources/EnvironmentKeys.swift new file mode 100644 index 0000000..8370585 --- /dev/null +++ b/Sources/EnvironmentKeys.swift @@ -0,0 +1,45 @@ +// +// EnvironmentKeys.swift +// CoreStore +// +// Created by John Rommel Estropia on 2019/10/05. +// Copyright © 2019 John Rommel Estropia. All rights reserved. +// + +#if canImport(SwiftUI) + +import SwiftUI + + +// MARK: - DataStackEnvironmentKey + +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +public struct DataStackEnvironmentKey: EnvironmentKey { + + // MARK: Public + + public static var defaultValue: DataStack { + + return Shared.defaultStack + } +} + + +// MARK: - EnvironmentValues + +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +extension EnvironmentValues { + + // MARK: Public + + public var dataStack: DataStack { + get { + return self[DataStackEnvironmentKey.self] + } + set { + self[DataStackEnvironmentKey.self] = newValue + } + } +} + +#endif diff --git a/Sources/ListSnapshot.swift b/Sources/ListSnapshot.swift new file mode 100644 index 0000000..4ce0717 --- /dev/null +++ b/Sources/ListSnapshot.swift @@ -0,0 +1,131 @@ +// +// ListSnapshot.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) + +import CoreData + +#if canImport(UIKit) +import UIKit + +#elseif canImport(AppKit) +import AppKit + +#endif + + +// MARK: - LiveList + +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +public struct ListSnapshot: SnapshotResult, RandomAccessCollection, Hashable { + + // MARK: Public + + public subscript(indices: S) -> [ObjectType] where S.Element == Index { + + let context = self.context! + let objectIDs = self.snapshotStruct.itemIdentifiers + return indices.map { position in + + let objectID = objectIDs[position] + return context.fetchExisting(objectID)! + } + } + + + // MARK: SnapshotResult + + public typealias ObjectType = D + + + // MARK: RandomAccessCollection + + public var startIndex: Index { + + return 0 + } + + public var endIndex: Index { + + return self.snapshotStruct.numberOfItems + } + + public subscript(position: Index) -> ObjectType { + + let context = self.context! + let objectID = self.snapshotStruct.itemIdentifiers[position] + return context.fetchExisting(objectID)! + } + + + // MARK: Sequence + + public typealias Element = ObjectType + + public typealias Index = Int + + + // MARK: Equatable + + public static func == (_ lhs: Self, _ rhs: Self) -> Bool { + + return lhs.id == rhs.id + } + + + // MARK: Hashable + + public func hash(into hasher: inout Hasher) { + + hasher.combine(self.id) + } + + + // MARK: Internal + + internal init() { + + self.snapshotReference = .init() + self.snapshotStruct = self.snapshotReference as NSDiffableDataSourceSnapshot + self.context = nil + } + + internal init(snapshotReference: NSDiffableDataSourceSnapshotReference, context: NSManagedObjectContext) { + + self.snapshotReference = snapshotReference + self.snapshotStruct = snapshotReference as NSDiffableDataSourceSnapshot + self.context = context + } + + + // MARK: Private + + private let id: UUID = .init() + private let snapshotReference: NSDiffableDataSourceSnapshotReference + private let snapshotStruct: NSDiffableDataSourceSnapshot + private let context: NSManagedObjectContext? +} + +#endif diff --git a/Sources/LiveList.swift b/Sources/LiveList.swift index 05818dd..b87765e 100644 --- a/Sources/LiveList.swift +++ b/Sources/LiveList.swift @@ -35,6 +35,11 @@ import AppKit #endif +#if canImport(Combine) +import Combine + +#endif + #if canImport(SwiftUI) import SwiftUI @@ -44,58 +49,41 @@ import SwiftUI // MARK: - LiveList @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) -public final class LiveList: Hashable { +public final class LiveList { - // MARK: Public (Accessors) - - /** - The type for the objects contained bye the `ListMonitor` - */ - public typealias ObjectType = D - - public fileprivate(set) var snapshot: Snapshot = .empty { - - didSet { + // MARK: Public + public fileprivate(set) var snapshot: ListSnapshot = .init() { + willSet { + #if canImport(Combine) - - let newValue = self.snapshot + + let oldValue = self.snapshot guard newValue != oldValue else { return } - #if canImport(SwiftUI) withAnimation { - self.objectWillChange.send() } - + #else self.objectWillChange.send() - + #endif - + #endif } } - - - // MARK: Equatable - - public static func == (_ lhs: LiveList, _ rhs: LiveList) -> Bool { - - return lhs === rhs - } - - - // MARK: Hashable - - public func hash(into hasher: inout Hasher) { - - hasher.combine(ObjectIdentifier(self)) - } + + + // MARK: LiveResult + + public typealias ObjectType = D + + public typealias SnapshotType = ListSnapshot // MARK: Internal @@ -273,7 +261,7 @@ public final class LiveList: Hashable { // transactionQueue.async { // -// try! self.fetchedResultsController.performFetchFromSpecifiedStores() +// try!internal self.fetchedResultsController.performFetchFromSpecifiedStores() // self.taskGroup.notify(queue: .main) { // // createAsynchronously(self) @@ -285,108 +273,6 @@ public final class LiveList: Hashable { try! self.fetchedResultsController.performFetchFromSpecifiedStores() } } - - - // MARK: - Snapshot - - public struct Snapshot: RandomAccessCollection, Hashable { - - public subscript(indices: IndexSet) -> [ObjectType] { - - let context = self.context! - let objectIDs = self.snapshotStruct.itemIdentifiers - return indices.map { position in - - let objectID = objectIDs[position] - return context.fetchExisting(objectID)! - } - } - - // MARK: RandomAccessCollection - - public var startIndex: Index { - - return 0 - } - - public var endIndex: Index { - - return self.snapshotStruct.numberOfItems - } - - public subscript(position: Index) -> ObjectType { - - let context = self.context! - let objectID = self.snapshotStruct.itemIdentifiers[position] - return context.fetchExisting(objectID)! - } - - - // MARK: Sequence - - public typealias Element = ObjectType - - public typealias Index = Int - -// public typealias SubSequence = Slice> -// -// /// A type that represents the indices that are valid for subscripting the -// /// collection, in ascending order. -// public typealias Indices = Range -// -// /// A type that provides the collection's iteration interface and -// /// encapsulates its iteration state. -// /// -// /// By default, a collection conforms to the `Sequence` protocol by -// /// supplying `IndexingIterator` as its associated `Iterator` -// /// type. -// public typealias Iterator = IndexingIterator> - - - // MARK: Equatable - - public static func == (_ lhs: Snapshot, _ rhs: Snapshot) -> Bool { - - return lhs.snapshotReference == rhs.snapshotReference - } - - - // MARK: Hashable - - public func hash(into hasher: inout Hasher) { - - hasher.combine(self.snapshotReference) - } - - - // MARK: Internal - - internal static var empty: Snapshot { - - return .init() - } - - internal init(snapshotReference: NSDiffableDataSourceSnapshotReference, context: NSManagedObjectContext) { - - self.snapshotReference = snapshotReference - self.snapshotStruct = snapshotReference as NSDiffableDataSourceSnapshot - self.context = context - } - - - // MARK: Private - - private let snapshotReference: NSDiffableDataSourceSnapshotReference - private let snapshotStruct: NSDiffableDataSourceSnapshot - private let context: NSManagedObjectContext? - - private init() { - - self.snapshotReference = .init() - self.snapshotStruct = self.snapshotReference as NSDiffableDataSourceSnapshot - self.context = nil - } - } } @@ -407,10 +293,10 @@ extension LiveList: FetchedDiffableDataSourceSnapshotHandler { #if canImport(Combine) import Combine -// MARK: - LiveList: ObservableObject +// MARK: - LiveList: LiveResult @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) -extension LiveList: ObservableObject { +extension LiveList: LiveResult { // MARK: ObservableObject diff --git a/Sources/LiveQuery.swift b/Sources/LiveQuery.swift new file mode 100644 index 0000000..5ecdd67 --- /dev/null +++ b/Sources/LiveQuery.swift @@ -0,0 +1,165 @@ +// +// LiveQuery.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(SwiftUI) && canImport(Combine) + +import CoreData +import Combine +import SwiftUI + + +#warning("TODO: autoupdating doesn't work yet") +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +@propertyWrapper +public struct LiveQuery: DynamicProperty { + + // MARK: Public + + @Environment(\.dataStack) + public var dataStack: DataStack + + public typealias ObjectType = Result.ObjectType + + + // MARK: @propertyWrapper + + public fileprivate(set) var wrappedValue: Result { + + get { + + return self.nonMutatingWrappedValue.wrappedValue + } + set { + + self.nonMutatingWrappedValue = LazyNonmutating { newValue } + } + } + + public var projectedValue: Result { + + return self.wrappedValue + } + + + // MARK: DynamicProperty + + public mutating func update() { + + SwiftUI.withAnimation { + + let dataStack = self.dataStack + if self.set(dataStack: dataStack) { + + return + } + self.wrappedValue = self.newWrappedValue(dataStack) + } + } + + + // MARK: FilePrivate + + fileprivate let newWrappedValue: (DataStack) -> Result + + fileprivate init(newWrappedValue: @escaping (DataStack) -> Result) { + + self.newWrappedValue = newWrappedValue + } + + + // MARK: Private + + private var nonMutatingWrappedValue: LazyNonmutating = .init { fatalError() } + + private var currentDataStack: DataStack? + + private mutating func set(dataStack: DataStack) -> Bool { + + guard self.currentDataStack != dataStack else { + + return false + } + self.currentDataStack = dataStack + + let newWrappedValue = self.newWrappedValue + self.nonMutatingWrappedValue = LazyNonmutating { + + newWrappedValue(dataStack) + } + return true + } + + + // MARK: - LazyNonmutating + + fileprivate final class LazyNonmutating { + + // MARK: FilePrivate + + lazy var wrappedValue: Value = self.initializer() + + init(_ initializer: @escaping () -> Value) { + + self.initializer = initializer + } + + + // MARK: Private + + private var initializer: () -> Value + } +} + + +#if canImport(UIKit) || canImport(AppKit) + +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +extension LiveQuery { + + public init(liveList: LiveList) where Result == LiveList { + + self.init( + newWrappedValue: { _ in liveList } + ) + } + + public init(_ clauseChain: FetchChainBuilder) where Result == LiveList { + + self.init( + newWrappedValue: { $0.liveList(clauseChain) } + ) + } + + public init(_ clauseChain: SectionMonitorChainBuilder) where Result == LiveList { + + self.init( + newWrappedValue: { $0.liveList(clauseChain) } + ) + } +} + +#endif + +#endif diff --git a/Sources/LiveResult.swift b/Sources/LiveResult.swift new file mode 100644 index 0000000..407eb25 --- /dev/null +++ b/Sources/LiveResult.swift @@ -0,0 +1,46 @@ +// +// 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 + +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +public protocol LiveResult: ObservableObject { + + associatedtype ObjectType + associatedtype SnapshotType: SnapshotResult where SnapshotType.ObjectType == Self.ObjectType +} + +#endif diff --git a/Sources/Shared.swift b/Sources/Shared.swift index 604a5ec..8810826 100644 --- a/Sources/Shared.swift +++ b/Sources/Shared.swift @@ -38,7 +38,6 @@ public enum Shared { */ public static var logger: CoreStoreLogger = DefaultLogger() - @available(*, deprecated, message: "Call methods directly from the DataStack instead") public static var defaultStack: DataStack { get { diff --git a/Sources/SnapshotResult.swift b/Sources/SnapshotResult.swift new file mode 100644 index 0000000..e22bfb6 --- /dev/null +++ b/Sources/SnapshotResult.swift @@ -0,0 +1,45 @@ +// +// 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 + +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 15.0, *) +public protocol SnapshotResult { + + associatedtype ObjectType: DynamicObject +} + +#endif