mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-06 13:20:12 +01:00
Prototyping SwiftUI utilities
This commit is contained in:
@@ -734,6 +734,30 @@
|
||||
B5BF7FCC234D80910070E741 /* Internals.LazyNonmutating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FCA234D80910070E741 /* Internals.LazyNonmutating.swift */; };
|
||||
B5BF7FCD234D80910070E741 /* Internals.LazyNonmutating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FCA234D80910070E741 /* Internals.LazyNonmutating.swift */; };
|
||||
B5BF7FCE234D80910070E741 /* Internals.LazyNonmutating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BF7FCA234D80910070E741 /* Internals.LazyNonmutating.swift */; };
|
||||
B5C7958F25D7D18000BDACC1 /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7958E25D7D18000BDACC1 /* LiveList.swift */; };
|
||||
B5C7959025D7D18000BDACC1 /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7958E25D7D18000BDACC1 /* LiveList.swift */; };
|
||||
B5C7959125D7D18000BDACC1 /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7958E25D7D18000BDACC1 /* LiveList.swift */; };
|
||||
B5C7959225D7D18000BDACC1 /* LiveList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7958E25D7D18000BDACC1 /* LiveList.swift */; };
|
||||
B5C7959425D7D18700BDACC1 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959325D7D18700BDACC1 /* LiveObject.swift */; };
|
||||
B5C7959525D7D18700BDACC1 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959325D7D18700BDACC1 /* LiveObject.swift */; };
|
||||
B5C7959625D7D18700BDACC1 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959325D7D18700BDACC1 /* LiveObject.swift */; };
|
||||
B5C7959725D7D18700BDACC1 /* LiveObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959325D7D18700BDACC1 /* LiveObject.swift */; };
|
||||
B5C7959925D7D8B300BDACC1 /* ListReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959825D7D8B300BDACC1 /* ListReader.swift */; };
|
||||
B5C7959A25D7D8B300BDACC1 /* ListReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959825D7D8B300BDACC1 /* ListReader.swift */; };
|
||||
B5C7959B25D7D8B300BDACC1 /* ListReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959825D7D8B300BDACC1 /* ListReader.swift */; };
|
||||
B5C7959C25D7D8B300BDACC1 /* ListReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C7959825D7D8B300BDACC1 /* ListReader.swift */; };
|
||||
B5C795A125D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795A025D7EB2200BDACC1 /* ForEach+SwiftUI.swift */; };
|
||||
B5C795A225D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795A025D7EB2200BDACC1 /* ForEach+SwiftUI.swift */; };
|
||||
B5C795A325D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795A025D7EB2200BDACC1 /* ForEach+SwiftUI.swift */; };
|
||||
B5C795A425D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795A025D7EB2200BDACC1 /* ForEach+SwiftUI.swift */; };
|
||||
B5C795AB25D7ED8600BDACC1 /* SectionsReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AA25D7ED8600BDACC1 /* SectionsReader.swift */; };
|
||||
B5C795AC25D7ED8600BDACC1 /* SectionsReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AA25D7ED8600BDACC1 /* SectionsReader.swift */; };
|
||||
B5C795AD25D7ED8600BDACC1 /* SectionsReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AA25D7ED8600BDACC1 /* SectionsReader.swift */; };
|
||||
B5C795AE25D7ED8600BDACC1 /* SectionsReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AA25D7ED8600BDACC1 /* SectionsReader.swift */; };
|
||||
B5C795B025D7EF8600BDACC1 /* ForEachSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AF25D7EF8600BDACC1 /* ForEachSection.swift */; };
|
||||
B5C795B125D7EF8600BDACC1 /* ForEachSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AF25D7EF8600BDACC1 /* ForEachSection.swift */; };
|
||||
B5C795B225D7EF8600BDACC1 /* ForEachSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AF25D7EF8600BDACC1 /* ForEachSection.swift */; };
|
||||
B5C795B325D7EF8600BDACC1 /* ForEachSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795AF25D7EF8600BDACC1 /* ForEachSection.swift */; };
|
||||
B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */; };
|
||||
B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */; };
|
||||
B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */; };
|
||||
@@ -1168,6 +1192,12 @@
|
||||
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>"; };
|
||||
B5C7958E25D7D18000BDACC1 /* LiveList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveList.swift; sourceTree = "<group>"; };
|
||||
B5C7959325D7D18700BDACC1 /* LiveObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveObject.swift; sourceTree = "<group>"; };
|
||||
B5C7959825D7D8B300BDACC1 /* ListReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListReader.swift; sourceTree = "<group>"; };
|
||||
B5C795A025D7EB2200BDACC1 /* ForEach+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ForEach+SwiftUI.swift"; sourceTree = "<group>"; };
|
||||
B5C795AA25D7ED8600BDACC1 /* SectionsReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionsReader.swift; sourceTree = "<group>"; };
|
||||
B5C795AF25D7EF8600BDACC1 /* ForEachSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForEachSection.swift; sourceTree = "<group>"; };
|
||||
B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; };
|
||||
B5C976E61C6E3A5900B1AF90 /* Internals.CoreStoreFetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Internals.CoreStoreFetchedResultsController.swift; sourceTree = "<group>"; };
|
||||
B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhereClauseType.swift; sourceTree = "<group>"; };
|
||||
@@ -1543,7 +1573,9 @@
|
||||
B52FEC722596DB6400368BFB /* SwiftUI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B52FEC732596DBE000368BFB /* ObjectReader.swift */,
|
||||
B5C7959F25D7EB1200BDACC1 /* Extensions */,
|
||||
B5C7959E25D7E8B100BDACC1 /* Views */,
|
||||
B5C7959D25D7E89B00BDACC1 /* PropertyWrappers */,
|
||||
);
|
||||
name = SwiftUI;
|
||||
sourceTree = "<group>";
|
||||
@@ -1710,6 +1742,7 @@
|
||||
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */,
|
||||
B549F6721E56A92800FBAB2D /* CoreDataNativeType.swift */,
|
||||
B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */,
|
||||
B5C795BE25D933C200BDACC1 /* Reactive Programming */,
|
||||
B52FEC722596DB6400368BFB /* SwiftUI */,
|
||||
B5E84EDA1AFF84500064E85B /* Setup */,
|
||||
B51B5C2922D43854009FA3BA /* KeyPaths */,
|
||||
@@ -1744,6 +1777,41 @@
|
||||
name = TestEntities;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5C7959D25D7E89B00BDACC1 /* PropertyWrappers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5C7958E25D7D18000BDACC1 /* LiveList.swift */,
|
||||
B5C7959325D7D18700BDACC1 /* LiveObject.swift */,
|
||||
);
|
||||
name = PropertyWrappers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5C7959E25D7E8B100BDACC1 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B52FEC732596DBE000368BFB /* ObjectReader.swift */,
|
||||
B5C7959825D7D8B300BDACC1 /* ListReader.swift */,
|
||||
B5C795AA25D7ED8600BDACC1 /* SectionsReader.swift */,
|
||||
B5C795AF25D7EF8600BDACC1 /* ForEachSection.swift */,
|
||||
);
|
||||
name = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5C7959F25D7EB1200BDACC1 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5C795A025D7EB2200BDACC1 /* ForEach+SwiftUI.swift */,
|
||||
);
|
||||
name = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5C795BE25D933C200BDACC1 /* Reactive Programming */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = "Reactive Programming";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5DBE2CB1C99148100B5CEFA /* ObjectiveC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2314,6 +2382,7 @@
|
||||
B596BBBB1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B55BB4D4235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
B5C795AB25D7ED8600BDACC1 /* SectionsReader.swift in Sources */,
|
||||
B5ECDC051CA8138100C7F112 /* CSOrderBy.swift in Sources */,
|
||||
B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
|
||||
B5DAFB4A2203E01D003FCCD0 /* KeyPathGenericBindings.swift in Sources */,
|
||||
@@ -2368,6 +2437,7 @@
|
||||
B546F9731C9C553300D5AC55 /* SetupResult.swift in Sources */,
|
||||
B50C3EFE23D1AB1400B29880 /* FieldCoders.Plist.swift in Sources */,
|
||||
B56E4EDF23CEBCF000E1708C /* FieldOptionalType.swift in Sources */,
|
||||
B5C7959925D7D8B300BDACC1 /* ListReader.swift in Sources */,
|
||||
B53CA9A21EF1EF1600E0F440 /* PartialObject.swift in Sources */,
|
||||
B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */,
|
||||
B5E84F111AFF847B0064E85B /* Select.swift in Sources */,
|
||||
@@ -2389,6 +2459,7 @@
|
||||
B5E84F2F1AFF849C0064E85B /* Internals.NotificationObserver.swift in Sources */,
|
||||
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */,
|
||||
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */,
|
||||
B5C7958F25D7D18000BDACC1 /* LiveList.swift in Sources */,
|
||||
B5FE4DAC1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
|
||||
B501FDE71CA8D20500BE22EF /* CSListObserver.swift in Sources */,
|
||||
B5E41EC01EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
|
||||
@@ -2437,6 +2508,7 @@
|
||||
B56E4ECF23CD9E4200E1708C /* Field.Stored.swift in Sources */,
|
||||
B52F744A1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
|
||||
B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
|
||||
B5C795B025D7EF8600BDACC1 /* ForEachSection.swift in Sources */,
|
||||
B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
|
||||
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
|
||||
B56923E81EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
@@ -2462,6 +2534,7 @@
|
||||
B538BA771D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
|
||||
B51B5C2B22D43931009FA3BA /* String+KeyPaths.swift in Sources */,
|
||||
B512607F1E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */,
|
||||
B5C7959425D7D18700BDACC1 /* LiveObject.swift in Sources */,
|
||||
B509D7CE23C8492800F42824 /* Relationship.ToManyUnordered.swift in Sources */,
|
||||
B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */,
|
||||
B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
@@ -2481,6 +2554,7 @@
|
||||
B53D9E5923513712000F48FB /* DiffableDataSourceSnapshotProtocol.swift in Sources */,
|
||||
B56E4ED923CEB8E700E1708C /* FieldStorableType.swift in Sources */,
|
||||
B5474D152227C08700B21FEC /* Internals.CoreStoreFetchRequest.swift in Sources */,
|
||||
B5C795A125D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */,
|
||||
B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5215CAE1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
@@ -2567,6 +2641,7 @@
|
||||
B596BBBC1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
B55BB4D5235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
B5C795AC25D7ED8600BDACC1 /* SectionsReader.swift in Sources */,
|
||||
B5ECDC071CA8138100C7F112 /* CSOrderBy.swift in Sources */,
|
||||
B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
|
||||
B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
|
||||
@@ -2621,6 +2696,7 @@
|
||||
B5FE4DA81C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
|
||||
B50C3EFF23D1AB1400B29880 /* FieldCoders.Plist.swift in Sources */,
|
||||
B56E4EE023CEBCF000E1708C /* FieldOptionalType.swift in Sources */,
|
||||
B5C7959A25D7D8B300BDACC1 /* ListReader.swift in Sources */,
|
||||
B5F8496D234898240029D57B /* ListSnapshot.swift in Sources */,
|
||||
B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
|
||||
B5DBE2D31C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
|
||||
@@ -2642,6 +2718,7 @@
|
||||
B501FDE41CA8D1F500BE22EF /* CSListMonitor.swift in Sources */,
|
||||
B5A1DAC91F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
|
||||
B5FE4DA31C8481E100FA6A91 /* StorageInterface.swift in Sources */,
|
||||
B5C7959025D7D18000BDACC1 /* LiveList.swift in Sources */,
|
||||
B5ECDC131CA816E500C7F112 /* CSTweak.swift in Sources */,
|
||||
B56923C51EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
|
||||
82BA18C91C4BBD5900A0916E /* MigrationType.swift in Sources */,
|
||||
@@ -2690,6 +2767,7 @@
|
||||
82BA18D81C4BBD7100A0916E /* Internals.WeakObject.swift in Sources */,
|
||||
B56923E91EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5C795B125D7EF8600BDACC1 /* ForEachSection.swift in Sources */,
|
||||
B509D7BD23C8480A00F42824 /* Value.Required.swift in Sources */,
|
||||
B5215CA51FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
|
||||
B5D33A021E96012400C880DE /* Relationship.swift in Sources */,
|
||||
@@ -2715,6 +2793,7 @@
|
||||
B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B5277673234F1AEB0056BE9F /* NSManagedObjectContext+Logging.swift in Sources */,
|
||||
B509D7D923C84E2600F42824 /* Transformable.Optional.swift in Sources */,
|
||||
B5C7959525D7D18700BDACC1 /* LiveObject.swift in Sources */,
|
||||
B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
82BA18A81C4BBD2900A0916E /* CoreStoreLogger.swift in Sources */,
|
||||
B549F65F1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
@@ -2734,6 +2813,7 @@
|
||||
B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B56E4EDA23CEB8E700E1708C /* FieldStorableType.swift in Sources */,
|
||||
B5215CAF1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
B5C795A225D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */,
|
||||
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
B56923ED1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
82BA18B91C4BBD4A00A0916E /* From.swift in Sources */,
|
||||
@@ -2820,6 +2900,7 @@
|
||||
B56923FD1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
|
||||
B55514ED1EED8BF900BAB888 /* From+Querying.swift in Sources */,
|
||||
B5BF7FC4234D7B2E0070E741 /* ObjectPublisher.swift in Sources */,
|
||||
B5C795AE25D7ED8600BDACC1 /* SectionsReader.swift in Sources */,
|
||||
B596BBBE1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B55BB4D7235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
@@ -2874,6 +2955,7 @@
|
||||
B53CA9A51EF1EF1600E0F440 /* PartialObject.swift in Sources */,
|
||||
B50C3F0123D1AB1400B29880 /* FieldCoders.Plist.swift in Sources */,
|
||||
B56E4EE223CEBCF000E1708C /* FieldOptionalType.swift in Sources */,
|
||||
B5C7959C25D7D8B300BDACC1 /* ListReader.swift in Sources */,
|
||||
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */,
|
||||
B53FBA1C1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */,
|
||||
B5F8496F234898240029D57B /* ListSnapshot.swift in Sources */,
|
||||
@@ -2895,6 +2977,7 @@
|
||||
B52DD19D1BE1F92C00949AFE /* BaseDataTransaction.swift in Sources */,
|
||||
B5220E131D1305ED009BC71E /* SectionBy.swift in Sources */,
|
||||
B559CD4D1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
|
||||
B5C7959225D7D18000BDACC1 /* LiveList.swift in Sources */,
|
||||
B5E41EC31EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
|
||||
B5ECDBE91CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
|
||||
B5A1DACB1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
|
||||
@@ -2943,6 +3026,7 @@
|
||||
B56923EB1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B50E175023517C03004F033C /* Internals.DiffableDataUIDispatcher.StagedChangeset.swift in Sources */,
|
||||
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5C795B325D7EF8600BDACC1 /* ForEachSection.swift in Sources */,
|
||||
B509D7C123C8480B00F42824 /* Value.Required.swift in Sources */,
|
||||
B5215CA71FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
|
||||
B5D33A041E96012400C880DE /* Relationship.swift in Sources */,
|
||||
@@ -2968,6 +3052,7 @@
|
||||
B5ECDC331CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */,
|
||||
B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */,
|
||||
B509D7DB23C84E2600F42824 /* Transformable.Optional.swift in Sources */,
|
||||
B5C7959725D7D18700BDACC1 /* LiveObject.swift in Sources */,
|
||||
B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
B5277675234F1AEB0056BE9F /* NSManagedObjectContext+Logging.swift in Sources */,
|
||||
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
@@ -2987,6 +3072,7 @@
|
||||
B501322E2346A9B100FC238B /* ListPublisher.swift in Sources */,
|
||||
B56E4EDC23CEB8E700E1708C /* FieldStorableType.swift in Sources */,
|
||||
B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B5C795A425D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */,
|
||||
B5215CB11FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B56923EF1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
@@ -3073,6 +3159,7 @@
|
||||
B596BBBD1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDC081CA8138100C7F112 /* CSOrderBy.swift in Sources */,
|
||||
B55BB4D6235012AE00C33E34 /* ObjectRepresentation.swift in Sources */,
|
||||
B5C795AD25D7ED8600BDACC1 /* SectionsReader.swift in Sources */,
|
||||
B5E1B59B1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
|
||||
B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
|
||||
B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
|
||||
@@ -3127,6 +3214,7 @@
|
||||
B5831F442212700500D8604C /* Where.Expression.swift in Sources */,
|
||||
B50C3F0023D1AB1400B29880 /* FieldCoders.Plist.swift in Sources */,
|
||||
B56E4EE123CEBCF000E1708C /* FieldOptionalType.swift in Sources */,
|
||||
B5C7959B25D7D8B300BDACC1 /* ListReader.swift in Sources */,
|
||||
B5F8496E234898240029D57B /* ListSnapshot.swift in Sources */,
|
||||
B51260951E9B28F100402229 /* Internals.EntityIdentifier.swift in Sources */,
|
||||
B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
|
||||
@@ -3148,6 +3236,7 @@
|
||||
B501FDE51CA8D1F500BE22EF /* CSListMonitor.swift in Sources */,
|
||||
B5E41EC21EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
|
||||
B5ECDC141CA816E500C7F112 /* CSTweak.swift in Sources */,
|
||||
B5C7959125D7D18000BDACC1 /* LiveList.swift in Sources */,
|
||||
B5A1DACA1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
|
||||
B56321AE1BD6521C006C9394 /* Internals.NotificationObserver.swift in Sources */,
|
||||
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */,
|
||||
@@ -3196,6 +3285,7 @@
|
||||
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
|
||||
B56321B61BD6521C006C9394 /* Internals.WeakObject.swift in Sources */,
|
||||
B56923EA1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B5C795B225D7EF8600BDACC1 /* ForEachSection.swift in Sources */,
|
||||
B509D7BF23C8480B00F42824 /* Value.Required.swift in Sources */,
|
||||
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5215CA61FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
|
||||
@@ -3221,6 +3311,7 @@
|
||||
B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B5277674234F1AEB0056BE9F /* NSManagedObjectContext+Logging.swift in Sources */,
|
||||
B509D7DA23C84E2600F42824 /* Transformable.Optional.swift in Sources */,
|
||||
B5C7959625D7D18700BDACC1 /* LiveObject.swift in Sources */,
|
||||
B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */,
|
||||
B549F6601E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
@@ -3240,6 +3331,7 @@
|
||||
B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
|
||||
B56E4EDB23CEB8E700E1708C /* FieldStorableType.swift in Sources */,
|
||||
B5215CB01FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
|
||||
B5C795A325D7EB2200BDACC1 /* ForEach+SwiftUI.swift in Sources */,
|
||||
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
B56923EE1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
|
||||
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */,
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
B54D2F7C251196B6004BEC7D /* Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54D2F7B251196B6004BEC7D /* Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift */; };
|
||||
B54D2F7E25119DCE004BEC7D /* Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B54D2F7D25119DCE004BEC7D /* Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel */; };
|
||||
B54D2F852511B70B004BEC7D /* Advanced.EvolutionDemo.CreaturesDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54D2F842511B70B004BEC7D /* Advanced.EvolutionDemo.CreaturesDataSource.swift */; };
|
||||
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E724F9D406001134A1 /* Modern.PokedexDemo.ListView.swift */; };
|
||||
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E924F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift */; };
|
||||
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift */; };
|
||||
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E724F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift */; };
|
||||
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E924F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift */; };
|
||||
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift */; };
|
||||
B566C8EE24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8ED24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift */; };
|
||||
B5931B4225124756007DA58E /* Advanced.EvolutionDemo.V1.FromV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5931B4125124756007DA58E /* Advanced.EvolutionDemo.V1.FromV2.swift */; };
|
||||
B5931B442512480A007DA58E /* Advanced.EvolutionDemo.V2.FromV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5931B432512480A007DA58E /* Advanced.EvolutionDemo.V2.FromV1.swift */; };
|
||||
@@ -68,7 +68,7 @@
|
||||
B5A391A024E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3919F24E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift */; };
|
||||
B5A391A224E8F01F00E7E8BD /* ⭐️Modern.ColorsDemo.UIKit.ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A124E8F01F00E7E8BD /* ⭐️Modern.ColorsDemo.UIKit.ListViewController.swift */; };
|
||||
B5A391A424E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A324E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift */; };
|
||||
B5A391A624E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A524E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift */; };
|
||||
B5A391A624E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A524E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift */; };
|
||||
B5A391AA24E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A924E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift */; };
|
||||
B5A391AC24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391AB24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift */; };
|
||||
B5A391AE24E9150F00E7E8BD /* ⭐️Modern.ColorsDemo.UIKit.DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391AD24E9150F00E7E8BD /* ⭐️Modern.ColorsDemo.UIKit.DetailViewController.swift */; };
|
||||
@@ -97,6 +97,7 @@
|
||||
B5A5440B25049492000DC5E3 /* Advanced.EvolutionDemo.V3.Creature.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5440A25049492000DC5E3 /* Advanced.EvolutionDemo.V3.Creature.swift */; };
|
||||
B5A5440D2504949C000DC5E3 /* Advanced.EvolutionDemo.V4.Creature.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5440C2504949C000DC5E3 /* Advanced.EvolutionDemo.V4.Creature.swift */; };
|
||||
B5C18F3325138700001BEFB3 /* Advanced.EvolutionDemo.ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C18F3225138700001BEFB3 /* Advanced.EvolutionDemo.ProgressView.swift */; };
|
||||
B5C795B625D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795B525D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift */; };
|
||||
B5D6F1F8250E07FD00DF5D2F /* Advanced.EvolutionDemo.V1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D6F1F7250E07FD00DF5D2F /* Advanced.EvolutionDemo.V1.swift */; };
|
||||
B5D6F1FC250E0B1700DF5D2F /* Advanced.EvolutionDemo.V2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D6F1FB250E0B1700DF5D2F /* Advanced.EvolutionDemo.V2.swift */; };
|
||||
B5D6F1FE250E0B3F00DF5D2F /* Advanced.EvolutionDemo.GeologicalPeriod.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D6F1FD250E0B3F00DF5D2F /* Advanced.EvolutionDemo.GeologicalPeriod.swift */; };
|
||||
@@ -133,9 +134,9 @@
|
||||
B54D2F7B251196B6004BEC7D /* Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
B54D2F7D25119DCE004BEC7D /* Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel; sourceTree = "<group>"; };
|
||||
B54D2F842511B70B004BEC7D /* Advanced.EvolutionDemo.CreaturesDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.CreaturesDataSource.swift; sourceTree = "<group>"; };
|
||||
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.ListView.swift; sourceTree = "<group>"; };
|
||||
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.ListViewController.swift; sourceTree = "<group>"; };
|
||||
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.ItemCell.swift; sourceTree = "<group>"; };
|
||||
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.ListView.swift; sourceTree = "<group>"; };
|
||||
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.ListViewController.swift; sourceTree = "<group>"; };
|
||||
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.ItemCell.swift; sourceTree = "<group>"; };
|
||||
B566C8ED24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.Details.swift; sourceTree = "<group>"; };
|
||||
B5931B4125124756007DA58E /* Advanced.EvolutionDemo.V1.FromV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V1.FromV2.swift; sourceTree = "<group>"; };
|
||||
B5931B432512480A007DA58E /* Advanced.EvolutionDemo.V2.FromV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V2.FromV1.swift; sourceTree = "<group>"; };
|
||||
@@ -185,7 +186,7 @@
|
||||
B5A3919F24E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.swift; sourceTree = "<group>"; };
|
||||
B5A391A124E8F01F00E7E8BD /* ⭐️Modern.ColorsDemo.UIKit.ListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "⭐️Modern.ColorsDemo.UIKit.ListViewController.swift"; sourceTree = "<group>"; };
|
||||
B5A391A324E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.ListView.swift; sourceTree = "<group>"; };
|
||||
B5A391A524E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "⭐️Modern.ColorsDemo.MainView.swift"; sourceTree = "<group>"; };
|
||||
B5A391A524E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.MainView.swift; sourceTree = "<group>"; };
|
||||
B5A391A924E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.ItemCell.swift; sourceTree = "<group>"; };
|
||||
B5A391AB24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.DetailView.swift; sourceTree = "<group>"; };
|
||||
B5A391AD24E9150F00E7E8BD /* ⭐️Modern.ColorsDemo.UIKit.DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "⭐️Modern.ColorsDemo.UIKit.DetailViewController.swift"; sourceTree = "<group>"; };
|
||||
@@ -214,6 +215,7 @@
|
||||
B5A5440A25049492000DC5E3 /* Advanced.EvolutionDemo.V3.Creature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V3.Creature.swift; sourceTree = "<group>"; };
|
||||
B5A5440C2504949C000DC5E3 /* Advanced.EvolutionDemo.V4.Creature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V4.Creature.swift; sourceTree = "<group>"; };
|
||||
B5C18F3225138700001BEFB3 /* Advanced.EvolutionDemo.ProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.ProgressView.swift; sourceTree = "<group>"; };
|
||||
B5C795B525D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.swift; sourceTree = "<group>"; };
|
||||
B5D6F1F7250E07FD00DF5D2F /* Advanced.EvolutionDemo.V1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V1.swift; sourceTree = "<group>"; };
|
||||
B5D6F1FB250E0B1700DF5D2F /* Advanced.EvolutionDemo.V2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V2.swift; sourceTree = "<group>"; };
|
||||
B5D6F1FD250E0B3F00DF5D2F /* Advanced.EvolutionDemo.GeologicalPeriod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.GeologicalPeriod.swift; sourceTree = "<group>"; };
|
||||
@@ -412,7 +414,7 @@
|
||||
children = (
|
||||
B5A3918E24E7E06500E7E8BD /* Modern.ColorsDemo.swift */,
|
||||
B5A3919724E7E67000E7E8BD /* Modern.ColorsDemo.Filter.swift */,
|
||||
B5A391A524E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift */,
|
||||
B5A391A524E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift */,
|
||||
B5A3919C24E8EE9000E7E8BD /* ⭐️UIKit */,
|
||||
B5A3919B24E8EE8100E7E8BD /* ⭐️SwiftUI */,
|
||||
B5A3919024E7E0B000E7E8BD /* Models */,
|
||||
@@ -458,9 +460,7 @@
|
||||
B5A391B024E96AF600E7E8BD /* Modern.PokedexDemo.swift */,
|
||||
B531EFEA24EB5ECD005F247D /* ⭐️Modern.PokedexDemo.Service.swift */,
|
||||
B531EFEC24EB7453005F247D /* Modern.PokedexDemo.MainView.swift */,
|
||||
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.ListView.swift */,
|
||||
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift */,
|
||||
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift */,
|
||||
B5C795B425D8EE1A00BDACC1 /* ⭐️UIKit */,
|
||||
B5A391B224E96B7400E7E8BD /* ⭐️Models */,
|
||||
);
|
||||
path = "⭐️PokedexDemo";
|
||||
@@ -549,6 +549,17 @@
|
||||
name = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5C795B425D8EE1A00BDACC1 /* ⭐️UIKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5C795B525D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift */,
|
||||
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift */,
|
||||
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift */,
|
||||
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift */,
|
||||
);
|
||||
name = "⭐️UIKit";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5D6F1F9250E08D200DF5D2F /* V1 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -704,6 +715,7 @@
|
||||
B5A543ED24FB84BE000DC5E3 /* Classic.ColorsDemo.MainView.swift in Sources */,
|
||||
B5A543DD24FB78F9000DC5E3 /* Classic.ColorsDemo.Palette.swift in Sources */,
|
||||
B5A3919824E7E67000E7E8BD /* Modern.ColorsDemo.Filter.swift in Sources */,
|
||||
B5C795B625D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift in Sources */,
|
||||
B5A3919224E7E0C600E7E8BD /* Modern.ColorsDemo.Palette.swift in Sources */,
|
||||
B5A3919E24E8EEB600E7E8BD /* Modern.ColorsDemo.SwiftUI.swift in Sources */,
|
||||
B5A391A024E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift in Sources */,
|
||||
@@ -711,16 +723,16 @@
|
||||
B5A3916024E6925900E7E8BD /* Modern.PlacemarksDemo.MapView.swift in Sources */,
|
||||
B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */,
|
||||
B566C8EE24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift in Sources */,
|
||||
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift in Sources */,
|
||||
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.ListView.swift in Sources */,
|
||||
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift in Sources */,
|
||||
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift in Sources */,
|
||||
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift in Sources */,
|
||||
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift in Sources */,
|
||||
B531EFED24EB7453005F247D /* Modern.PokedexDemo.MainView.swift in Sources */,
|
||||
B5A3918C24E7B44B00E7E8BD /* Modern.TimeZonesDemo.ItemView.swift in Sources */,
|
||||
B5A3918A24E7AD1800E7E8BD /* Modern.TimeZonesDemo.ListView.swift in Sources */,
|
||||
B5A3918624E7A54A00E7E8BD /* Modern.TimeZonesDemo.TimeZone.swift in Sources */,
|
||||
B5A543EB24FB84AF000DC5E3 /* ⭐️Classic.ColorsDemo.DetailViewController.swift in Sources */,
|
||||
B5A543F124FB84DD000DC5E3 /* ⭐️Classic.ColorsDemo.ListViewController.swift in Sources */,
|
||||
B5A391A624E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift in Sources */,
|
||||
B5A391A624E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift in Sources */,
|
||||
B5A3916224E697BA00E7E8BD /* ⭐️Modern.PlacemarksDemo.MainView.swift in Sources */,
|
||||
B5A391B424E96C0A00E7E8BD /* ⭐️Modern.PokedexDemo.Form.swift in Sources */,
|
||||
B531EFE924EB5A53005F247D /* ⭐️Modern.PokedexDemo.PokedexEntry.swift in Sources */,
|
||||
|
||||
@@ -20,8 +20,8 @@ struct InstructionsView: View {
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .center) {
|
||||
Color.white
|
||||
.cornerRadius(10)
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(Color.white)
|
||||
.shadow(color: Color(.sRGB, white: 0.5, opacity: 0.3), radius: 2, x: 1, y: 1)
|
||||
VStack(alignment: .leading, spacing: 3) {
|
||||
ForEach(self.rows, id: \.header) { row in
|
||||
|
||||
@@ -73,7 +73,9 @@ extension Menu {
|
||||
title: "Pokedex API",
|
||||
subtitle: "Importing JSON data from external source",
|
||||
destination: {
|
||||
Modern.PokedexDemo.MainView()
|
||||
Modern.PokedexDemo.MainView(
|
||||
listView: Modern.PokedexDemo.UIKit.ListView.init
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,17 +45,16 @@ extension Advanced.EvolutionDemo {
|
||||
.padding(.horizontal)
|
||||
GeometryReader { geometry in
|
||||
ZStack(alignment: .leading) {
|
||||
Color.gray
|
||||
.opacity(0.2)
|
||||
RoundedRectangle(cornerRadius: 4, style: .continuous)
|
||||
.fill(Color.gray.opacity(0.2))
|
||||
.frame(width: geometry.size.width, height: 8)
|
||||
.cornerRadius(4.0)
|
||||
Color.blue
|
||||
RoundedRectangle(cornerRadius: 4, style: .continuous)
|
||||
.fill(Color.blue)
|
||||
.frame(
|
||||
width: geometry.size.width
|
||||
* self.progressObserver.fractionCompleted,
|
||||
height: 8
|
||||
)
|
||||
.cornerRadius(4.0)
|
||||
}
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="16119" systemVersion="19F101" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17709" systemVersion="20C5048l" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Palette" representedClassName="Classic_ColorsDemo_Palette" syncable="YES">
|
||||
<attribute name="brightness" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="colorGroup" optional="YES" transient="YES" attributeType="String"/>
|
||||
<attribute name="hue" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="saturation" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<fetchedProperty name="testFetchProperty" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="Palette"/>
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="Palette" positionX="-63" positionY="-18" width="128" height="103"/>
|
||||
<element name="Palette" positionX="-63" positionY="-18" width="128" height="110"/>
|
||||
</elements>
|
||||
</model>
|
||||
@@ -13,12 +13,6 @@ extension Modern.ColorsDemo {
|
||||
|
||||
struct MainView<ListView: View, DetailView: View>: View {
|
||||
|
||||
/**
|
||||
⭐️ Sample 1: Setting a sectioned `ListPublisher` declared as an `@ObservedObject`
|
||||
*/
|
||||
@ObservedObject
|
||||
private var listPublisher: ListPublisher<Modern.ColorsDemo.Palette>
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
init(
|
||||
@@ -30,38 +24,24 @@ extension Modern.ColorsDemo {
|
||||
|
||||
self.listView = listView
|
||||
self.detailView = detailView
|
||||
self.listPublisher = Modern.ColorsDemo.palettesPublisher
|
||||
self._filter = Binding(
|
||||
get: { Modern.ColorsDemo.filter },
|
||||
set: { Modern.ColorsDemo.filter = $0 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
var body: some View {
|
||||
let detailView: AnyView
|
||||
if let selectedPalette = self.selectedPalette {
|
||||
|
||||
detailView = AnyView(
|
||||
self.detailView(selectedPalette)
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
detailView = AnyView(EmptyView())
|
||||
}
|
||||
let listPublisher = self.listPublisher
|
||||
return VStack(spacing: 0) {
|
||||
self.listView(listPublisher, { self.selectedPalette = $0 })
|
||||
self.listView(self.$palettes, { self.selectedPalette = $0 })
|
||||
.navigationBarTitle(
|
||||
Text("Colors (\(listPublisher.snapshot.numberOfItems) objects)")
|
||||
Text("Colors (\(self.palettes.count) objects)")
|
||||
)
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
detailView
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
self.selectedPalette.map {
|
||||
|
||||
self.detailView($0)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
.navigationBarItems(
|
||||
leading: HStack {
|
||||
@@ -91,6 +71,9 @@ extension Modern.ColorsDemo {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@LiveList(Modern.ColorsDemo.palettesPublisher)
|
||||
private var palettes: LiveList<Modern.ColorsDemo.Palette>.Items
|
||||
|
||||
private let listView: (
|
||||
_ listPublisher: ListPublisher<Modern.ColorsDemo.Palette>,
|
||||
_ onPaletteTapped: @escaping (ObjectPublisher<Modern.ColorsDemo.Palette>) -> Void
|
||||
@@ -103,12 +86,13 @@ extension Modern.ColorsDemo {
|
||||
@State
|
||||
private var selectedPalette: ObjectPublisher<Modern.ColorsDemo.Palette>?
|
||||
|
||||
@Binding
|
||||
private var filter: Modern.ColorsDemo.Filter
|
||||
@State
|
||||
private var filter: Modern.ColorsDemo.Filter = Modern.ColorsDemo.filter
|
||||
|
||||
private func changeFilter() {
|
||||
|
||||
Modern.ColorsDemo.filter = Modern.ColorsDemo.filter.next()
|
||||
self.filter = Modern.ColorsDemo.filter
|
||||
}
|
||||
|
||||
private func clearColors() {
|
||||
@@ -2,6 +2,7 @@
|
||||
// Demo
|
||||
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||
|
||||
import SwiftUI
|
||||
import CoreStore
|
||||
|
||||
// MARK: - Modern
|
||||
|
||||
@@ -17,8 +17,8 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
/**
|
||||
⭐️ Sample 1: Setting an `ObjectPublisher` declared as an `@ObservedObject`
|
||||
*/
|
||||
@ObservedObject
|
||||
private var palette: ObjectPublisher<Modern.ColorsDemo.Palette>
|
||||
@LiveObject
|
||||
private var palette: LiveObject<Modern.ColorsDemo.Palette>.Item?
|
||||
|
||||
/**
|
||||
⭐️ Sample 2: Setting properties that can be binded to controls (`Slider` in this case) by creating custom `@Binding` instances that updates the store when the values change.
|
||||
@@ -34,7 +34,7 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
|
||||
init(_ palette: ObjectPublisher<Modern.ColorsDemo.Palette>) {
|
||||
|
||||
self.palette = palette
|
||||
self._palette = .init(palette)
|
||||
self._hue = Binding(
|
||||
get: { palette.hue ?? 0 },
|
||||
set: { percentage in
|
||||
@@ -84,56 +84,50 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
|
||||
var body: some View {
|
||||
|
||||
guard let snapshot = self.palette.snapshot else {
|
||||
if let palette = self.palette {
|
||||
|
||||
return AnyView(EmptyView())
|
||||
}
|
||||
return AnyView(
|
||||
GeometryReader { geometry in
|
||||
ZStack(alignment: .bottom) {
|
||||
Color(snapshot.$color)
|
||||
ZStack {
|
||||
Color.white
|
||||
.cornerRadius(10)
|
||||
.shadow(color: Color(.sRGB, white: 0.5, opacity: 0.3), radius: 2, x: 1, y: 1)
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack {
|
||||
Text("H: \(Int(snapshot.$hue * 359))°")
|
||||
.frame(width: 80)
|
||||
Slider(
|
||||
value: self.$hue,
|
||||
in: 0 ... 1,
|
||||
step: 1 / 359
|
||||
)
|
||||
}
|
||||
HStack {
|
||||
Text("S: \(Int(snapshot.$saturation * 100))%")
|
||||
.frame(width: 80)
|
||||
Slider(
|
||||
value: self.$saturation,
|
||||
in: 0 ... 1,
|
||||
step: 1 / 100
|
||||
)
|
||||
}
|
||||
HStack {
|
||||
Text("B: \(Int(snapshot.$brightness * 100))%")
|
||||
.frame(width: 80)
|
||||
Slider(
|
||||
value: self.$brightness,
|
||||
in: 0 ... 1,
|
||||
step: 1 / 100
|
||||
)
|
||||
}
|
||||
ZStack(alignment: .center) {
|
||||
Color(palette.$color)
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(Color.white)
|
||||
.shadow(color: Color(.sRGB, white: 0.5, opacity: 0.3), radius: 2, x: 1, y: 1)
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack {
|
||||
Text("H: \(Int(palette.$hue * 359))°")
|
||||
.frame(width: 80)
|
||||
Slider(
|
||||
value: self.$hue,
|
||||
in: 0 ... 1,
|
||||
step: 1 / 359
|
||||
)
|
||||
}
|
||||
HStack {
|
||||
Text("S: \(Int(palette.$saturation * 100))%")
|
||||
.frame(width: 80)
|
||||
Slider(
|
||||
value: self.$saturation,
|
||||
in: 0 ... 1,
|
||||
step: 1 / 100
|
||||
)
|
||||
}
|
||||
HStack {
|
||||
Text("B: \(Int(palette.$brightness * 100))%")
|
||||
.frame(width: 80)
|
||||
Slider(
|
||||
value: self.$brightness,
|
||||
in: 0 ... 1,
|
||||
step: 1 / 100
|
||||
)
|
||||
}
|
||||
.foregroundColor(Color(.sRGB, white: 0, opacity: 0.8))
|
||||
.padding()
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.foregroundColor(Color(.sRGB, white: 0, opacity: 0.8))
|
||||
.padding()
|
||||
.padding(geometry.safeAreaInsets)
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
/**
|
||||
⭐️ Sample 1: Setting an `ObjectPublisher` declared as an `@ObservedObject`
|
||||
*/
|
||||
@ObservedObject
|
||||
private var palette: ObjectPublisher<Modern.ColorsDemo.Palette>
|
||||
@LiveObject
|
||||
private var palette: LiveObject<Modern.ColorsDemo.Palette>.Item?
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(_ palette: ObjectPublisher<Modern.ColorsDemo.Palette>) {
|
||||
|
||||
self.palette = palette
|
||||
self._palette = .init(palette)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,18 +32,16 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
|
||||
var body: some View {
|
||||
|
||||
guard let palette = self.palette.snapshot else {
|
||||
if let palette = self.palette {
|
||||
|
||||
return AnyView(EmptyView())
|
||||
}
|
||||
return AnyView(
|
||||
Color(palette.$color).overlay(
|
||||
Text(palette.$colorText)
|
||||
.foregroundColor(palette.$brightness > 0.6 ? .black : .white)
|
||||
.padding(),
|
||||
alignment: .leading
|
||||
)
|
||||
)
|
||||
.animation(.default)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import CoreStore
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - Modern.ColorsDemo.SwiftUI
|
||||
|
||||
extension Modern.ColorsDemo.SwiftUI {
|
||||
@@ -17,39 +16,43 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
/**
|
||||
⭐️ Sample 1: Setting a sectioned `ListPublisher` declared as an `@ObservedObject`
|
||||
*/
|
||||
@ObservedObject
|
||||
private var listPublisher: ListPublisher<Modern.ColorsDemo.Palette>
|
||||
@LiveList
|
||||
private var palettes: LiveList<Modern.ColorsDemo.Palette>.Items
|
||||
|
||||
/**
|
||||
⭐️ Sample 2: Assigning sections and items of the `ListPublisher` to corresponding `View`s
|
||||
*/
|
||||
var body: some View {
|
||||
let listSnapshot = self.listPublisher.snapshot
|
||||
return List {
|
||||
ForEach(listSnapshot.sectionIDs, id: \.self) { (sectionID) in
|
||||
|
||||
ForEachSection(in: self.palettes) { sectionID, palettes in
|
||||
|
||||
Section(header: Text(sectionID)) {
|
||||
ForEach(listSnapshot.items(inSectionWithID: sectionID), id: \.self) { palette in
|
||||
|
||||
ForEach(palettes) { palette in
|
||||
|
||||
Button(
|
||||
action: {
|
||||
|
||||
self.onPaletteTapped(palette)
|
||||
},
|
||||
label: {
|
||||
|
||||
Modern.ColorsDemo.SwiftUI.ItemView(palette)
|
||||
}
|
||||
)
|
||||
.listRowInsets(.init())
|
||||
}
|
||||
.onDelete { itemIndices in
|
||||
|
||||
|
||||
self.deleteColors(at: itemIndices, in: sectionID)
|
||||
}
|
||||
}
|
||||
}
|
||||
GeometryReader { geometry in
|
||||
Spacer(minLength: geometry.safeAreaInsets.bottom)
|
||||
}
|
||||
}
|
||||
.animation(.default)
|
||||
.listStyle(PlainListStyle())
|
||||
.edgesIgnoringSafeArea([])
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +63,7 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
onPaletteTapped: @escaping (ObjectPublisher<Modern.ColorsDemo.Palette>) -> Void
|
||||
) {
|
||||
|
||||
self.listPublisher = listPublisher
|
||||
self._palettes = .init(listPublisher)
|
||||
self.onPaletteTapped = onPaletteTapped
|
||||
}
|
||||
|
||||
@@ -71,7 +74,7 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
|
||||
private func deleteColors(at indices: IndexSet, in sectionID: String) {
|
||||
|
||||
let objectIDsToDelete = self.listPublisher.snapshot.itemIDs(
|
||||
let objectIDsToDelete = self.palettes.itemIDs(
|
||||
inSectionWithID: sectionID,
|
||||
atIndices: indices
|
||||
)
|
||||
|
||||
@@ -36,17 +36,13 @@ extension Modern.ColorsDemo.UIKit {
|
||||
*/
|
||||
private func startObservingList() {
|
||||
|
||||
let dataSource = self.dataSource
|
||||
self.listPublisher.addObserver(self) { (listPublisher) in
|
||||
|
||||
self.dataSource.apply(
|
||||
listPublisher.snapshot,
|
||||
animatingDifferences: true
|
||||
)
|
||||
dataSource.apply(listPublisher.snapshot, animatingDifferences: true)
|
||||
}
|
||||
self.dataSource.apply(
|
||||
listPublisher.snapshot,
|
||||
animatingDifferences: false
|
||||
)
|
||||
|
||||
dataSource.apply(self.listPublisher.snapshot, animatingDifferences: false)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,30 +12,28 @@ extension Modern.PokedexDemo {
|
||||
|
||||
// MARK: - Modern.PokedexDemo.MainView
|
||||
|
||||
struct MainView: View {
|
||||
struct MainView<ListView: View>: View {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
init() {
|
||||
|
||||
self.pokedexEntries = Modern.PokedexDemo.pokedexEntries
|
||||
|
||||
init(
|
||||
listView: @escaping () -> ListView
|
||||
) {
|
||||
|
||||
self.listView = listView
|
||||
}
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
var body: some View {
|
||||
let pokedexEntries = self.pokedexEntries.snapshot
|
||||
return ZStack {
|
||||
ZStack {
|
||||
|
||||
Modern.PokedexDemo.ListView(
|
||||
service: self.service,
|
||||
listPublisher: self.pokedexEntries
|
||||
)
|
||||
self.listView()
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
.edgesIgnoringSafeArea(.vertical)
|
||||
|
||||
if pokedexEntries.isEmpty {
|
||||
if self.pokedexEntries.isEmpty {
|
||||
|
||||
VStack(alignment: .center, spacing: 30) {
|
||||
Text("This demo needs to make a network connection to download Pokedex entries")
|
||||
@@ -64,11 +62,17 @@ extension Modern.PokedexDemo {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@ObservedObject
|
||||
private var pokedexEntries: ListPublisher<Modern.PokedexDemo.PokedexEntry>
|
||||
@LiveList(
|
||||
From<Modern.PokedexDemo.PokedexEntry>()
|
||||
.orderBy(.ascending(\.$index)),
|
||||
in: Modern.PokedexDemo.dataStack
|
||||
)
|
||||
private var pokedexEntries
|
||||
|
||||
@ObservedObject
|
||||
private var service: Modern.PokedexDemo.Service = .init()
|
||||
|
||||
private let listView: () -> ListView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +86,9 @@ struct _Demo_Modern_PokedexDemo_MainView_Preview: PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
Modern.PokedexDemo.MainView()
|
||||
Modern.PokedexDemo.MainView(
|
||||
listView: Modern.PokedexDemo.UIKit.ListView.init
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import CoreStore
|
||||
import UIKit
|
||||
|
||||
|
||||
// MARK: - Modern.PokedexDemo
|
||||
// MARK: - Modern.PokedexDemo.UIKit
|
||||
|
||||
extension Modern.PokedexDemo {
|
||||
extension Modern.PokedexDemo.UIKit {
|
||||
|
||||
// MARK: - Modern.PokedexDemo.ItemCell
|
||||
|
||||
@@ -17,7 +17,7 @@ extension Modern.PokedexDemo {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
static let reuseIdentifier: String = NSStringFromClass(Modern.PokedexDemo.ItemCell.self)
|
||||
static let reuseIdentifier: String = NSStringFromClass(Modern.PokedexDemo.UIKit.ItemCell.self)
|
||||
|
||||
func setPokedexEntry(
|
||||
_ pokedexEntry: Modern.PokedexDemo.PokedexEntry,
|
||||
@@ -61,6 +61,7 @@ extension Modern.PokedexDemo {
|
||||
|
||||
contentView.backgroundColor = UIColor.placeholderText.withAlphaComponent(0.1)
|
||||
contentView.layer.cornerRadius = 10
|
||||
contentView.layer.cornerCurve = .continuous
|
||||
contentView.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
import CoreStore
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Modern.PokedexDemo
|
||||
// MARK: - Modern.PokedexDemo.UIKit
|
||||
|
||||
extension Modern.PokedexDemo {
|
||||
extension Modern.PokedexDemo.UIKit {
|
||||
|
||||
// MARK: - Modern.PokedexDemo.ListView
|
||||
|
||||
@@ -15,19 +15,20 @@ extension Modern.PokedexDemo {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
init(
|
||||
service: Modern.PokedexDemo.Service,
|
||||
listPublisher: ListPublisher<Modern.PokedexDemo.PokedexEntry>
|
||||
) {
|
||||
init() {
|
||||
|
||||
self.service = service
|
||||
self.listPublisher = listPublisher
|
||||
self.service = Modern.PokedexDemo.Service.init()
|
||||
self.listPublisher = Modern.PokedexDemo.dataStack
|
||||
.publishList(
|
||||
From<Modern.PokedexDemo.PokedexEntry>()
|
||||
.orderBy(.ascending(\.$index))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: UIViewControllerRepresentable
|
||||
|
||||
typealias UIViewControllerType = Modern.PokedexDemo.ListViewController
|
||||
typealias UIViewControllerType = Modern.PokedexDemo.UIKit.ListViewController
|
||||
|
||||
func makeUIViewController(context: Self.Context) -> UIViewControllerType {
|
||||
|
||||
@@ -53,7 +54,7 @@ extension Modern.PokedexDemo {
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct _Demo_Modern_PokedexDemo_ListView_Preview: PreviewProvider {
|
||||
struct _Demo_Modern_PokedexDemo_UIKit_ListView_Preview: PreviewProvider {
|
||||
|
||||
// MARK: PreviewProvider
|
||||
|
||||
@@ -62,10 +63,7 @@ struct _Demo_Modern_PokedexDemo_ListView_Preview: PreviewProvider {
|
||||
let service = Modern.PokedexDemo.Service()
|
||||
service.fetchPokedexEntries()
|
||||
|
||||
return Modern.PokedexDemo.ListView(
|
||||
service: service,
|
||||
listPublisher: Modern.PokedexDemo.pokedexEntries
|
||||
)
|
||||
return Modern.PokedexDemo.UIKit.ListView()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import CoreStore
|
||||
import UIKit
|
||||
|
||||
|
||||
// MARK: - Modern.PokedexDemo
|
||||
// MARK: - Modern.PokedexDemo.UIKit
|
||||
|
||||
extension Modern.PokedexDemo {
|
||||
extension Modern.PokedexDemo.UIKit {
|
||||
|
||||
// MARK: - Modern.PokedexDemo.ListViewController
|
||||
|
||||
@@ -65,8 +65,8 @@ extension Modern.PokedexDemo {
|
||||
self.collectionView.backgroundColor = UIColor.systemBackground
|
||||
|
||||
self.collectionView.register(
|
||||
Modern.PokedexDemo.ItemCell.self,
|
||||
forCellWithReuseIdentifier: Modern.PokedexDemo.ItemCell.reuseIdentifier
|
||||
Modern.PokedexDemo.UIKit.ItemCell.self,
|
||||
forCellWithReuseIdentifier: Modern.PokedexDemo.UIKit.ItemCell.reuseIdentifier
|
||||
)
|
||||
|
||||
self.startObservingList()
|
||||
@@ -84,9 +84,9 @@ extension Modern.PokedexDemo {
|
||||
cellProvider: { (collectionView, indexPath, pokedexEntry) in
|
||||
|
||||
let cell = collectionView.dequeueReusableCell(
|
||||
withReuseIdentifier: Modern.PokedexDemo.ItemCell.reuseIdentifier,
|
||||
withReuseIdentifier: Modern.PokedexDemo.UIKit.ItemCell.reuseIdentifier,
|
||||
for: indexPath
|
||||
) as! Modern.PokedexDemo.ItemCell
|
||||
) as! Modern.PokedexDemo.UIKit.ItemCell
|
||||
cell.setPokedexEntry(pokedexEntry, service: self.service)
|
||||
return cell
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Demo
|
||||
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||
|
||||
|
||||
// MARK: - Modern.PokedexDemo
|
||||
|
||||
extension Modern.PokedexDemo {
|
||||
|
||||
// MARK: - UIKit
|
||||
|
||||
enum UIKit {}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ import CoreData
|
||||
Objective-C Foundation types that are natively supported by Core Data managed attributes all conform to `CoreDataNativeType`.
|
||||
*/
|
||||
@objc
|
||||
public protocol CoreDataNativeType: AnyObject, NSObjectProtocol {}
|
||||
public protocol CoreDataNativeType: NSObjectProtocol {}
|
||||
|
||||
|
||||
// MARK: - NSNumber
|
||||
|
||||
56
Sources/ForEach+SwiftUI.swift
Normal file
56
Sources/ForEach+SwiftUI.swift
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// ForEach+SwiftUI.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 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(Combine) && canImport(SwiftUI)
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - ForEach
|
||||
|
||||
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
|
||||
extension ForEach where Content: View {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
public init<O: DynamicObject>(
|
||||
_ listSnapshot: Data,
|
||||
@ViewBuilder content: @escaping (ObjectPublisher<O>) -> Content
|
||||
) where Data == LiveList<O>.Items, ID == O.ObjectID {
|
||||
|
||||
self.init(listSnapshot, id: \.cs_objectID, content: content)
|
||||
}
|
||||
|
||||
public init<O: DynamicObject>(
|
||||
_ objectPublishers: Data,
|
||||
@ViewBuilder content: @escaping (ObjectPublisher<O>) -> Content
|
||||
) where Data.Element == ObjectPublisher<O>, ID == O.ObjectID {
|
||||
|
||||
self.init(objectPublishers, id: \.cs_objectID, content: content)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
59
Sources/ForEachSection.swift
Normal file
59
Sources/ForEachSection.swift
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// ForEachSection.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Rommel Estropia on 2021/02/13.
|
||||
// Copyright © 2021 John Rommel Estropia. All rights reserved.
|
||||
//
|
||||
|
||||
#if canImport(Combine) && canImport(SwiftUI)
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - ForEachSection
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
public struct ForEachSection<Object: DynamicObject, Sections: View>: View {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
public init(
|
||||
in listSnapshot: LiveList<Object>.Items,
|
||||
@ViewBuilder sections: @escaping (
|
||||
_ sectionID: ListSnapshot<Object>.SectionID,
|
||||
_ objects: [ObjectPublisher<Object>]
|
||||
) -> Sections
|
||||
) {
|
||||
|
||||
self.listSnapshot = listSnapshot
|
||||
self.sections = sections
|
||||
}
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
public var body: some View {
|
||||
|
||||
ForEach(self.listSnapshot.sectionIDs, id: \.self) { sectionID in
|
||||
|
||||
self.sections(
|
||||
sectionID,
|
||||
self.listSnapshot.items(inSectionWithID: sectionID)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let listSnapshot: LiveList<Object>.Items
|
||||
|
||||
private let sections: (
|
||||
_ sectionID: ListSnapshot<Object>.SectionID,
|
||||
_ objects: [ObjectPublisher<Object>]
|
||||
) -> Sections
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -201,6 +201,14 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
public func cs_dataStack() -> DataStack? {
|
||||
|
||||
return self.context.parentStack
|
||||
}
|
||||
|
||||
|
||||
// MARK: Public (3rd Party Utilities)
|
||||
|
||||
78
Sources/ListReader.swift
Normal file
78
Sources/ListReader.swift
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// ListReader.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 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(Combine) && canImport(SwiftUI)
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - ListReader
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
public struct ListReader<Object: DynamicObject, Content: View, Value>: View {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
public init(
|
||||
_ listPublisher: ListPublisher<Object>,
|
||||
@ViewBuilder content: @escaping (Value) -> Content
|
||||
) where Value == LiveList<Object>.Items {
|
||||
|
||||
self._list = .init(listPublisher)
|
||||
self.content = content
|
||||
self.keyPath = \.self
|
||||
}
|
||||
|
||||
public init(
|
||||
_ listPublisher: ListPublisher<Object>,
|
||||
keyPath: KeyPath<LiveList<Object>.Items, Value>,
|
||||
@ViewBuilder content: @escaping (Value) -> Content
|
||||
) {
|
||||
|
||||
self._list = .init(listPublisher)
|
||||
self.content = content
|
||||
self.keyPath = keyPath
|
||||
}
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
public var body: some View {
|
||||
|
||||
self.content(self.list[keyPath: self.keyPath])
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@LiveList
|
||||
private var list: LiveList<Object>.Items
|
||||
|
||||
private let content: (Value) -> Content
|
||||
private let keyPath: KeyPath<LiveList<Object>.Items, Value>
|
||||
}
|
||||
|
||||
#endif
|
||||
162
Sources/LiveList.swift
Normal file
162
Sources/LiveList.swift
Normal file
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// LiveList.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 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(Combine) && canImport(SwiftUI)
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - LiveList
|
||||
|
||||
@propertyWrapper
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
public struct LiveList<Object: DynamicObject>: DynamicProperty {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
public typealias Items = ListSnapshot<Object>
|
||||
|
||||
public init(
|
||||
_ listPublisher: ListPublisher<Object>
|
||||
) {
|
||||
|
||||
self.observer = .init(listPublisher: listPublisher)
|
||||
}
|
||||
|
||||
public init(
|
||||
_ from: From<Object>,
|
||||
_ fetchClauses: FetchClause...,
|
||||
in dataStack: DataStack
|
||||
) {
|
||||
|
||||
self.init(from, fetchClauses, in: dataStack)
|
||||
}
|
||||
|
||||
public init(
|
||||
_ from: From<Object>,
|
||||
_ fetchClauses: [FetchClause],
|
||||
in dataStack: DataStack
|
||||
) {
|
||||
|
||||
self.init(dataStack.publishList(from, fetchClauses))
|
||||
}
|
||||
|
||||
public init<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B,
|
||||
in dataStack: DataStack
|
||||
) where B.ObjectType == Object {
|
||||
|
||||
self.init(dataStack.publishList(clauseChain))
|
||||
}
|
||||
|
||||
public init(
|
||||
_ from: From<Object>,
|
||||
_ sectionBy: SectionBy<Object>,
|
||||
_ fetchClauses: FetchClause...,
|
||||
in dataStack: DataStack
|
||||
) {
|
||||
|
||||
self.init(from, sectionBy, fetchClauses, in: dataStack)
|
||||
}
|
||||
|
||||
public init(
|
||||
_ from: From<Object>,
|
||||
_ sectionBy: SectionBy<Object>,
|
||||
_ fetchClauses: [FetchClause],
|
||||
in dataStack: DataStack
|
||||
) {
|
||||
|
||||
self.init(dataStack.publishList(from, sectionBy, fetchClauses))
|
||||
}
|
||||
|
||||
public init<B: SectionMonitorBuilderType>(
|
||||
_ clauseChain: B,
|
||||
in dataStack: DataStack
|
||||
) where B.ObjectType == Object {
|
||||
|
||||
self.init(dataStack.publishList(clauseChain))
|
||||
}
|
||||
|
||||
|
||||
// MARK: @propertyWrapper
|
||||
|
||||
public var wrappedValue: Items {
|
||||
|
||||
return self.observer.items
|
||||
}
|
||||
|
||||
public var projectedValue: ListPublisher<Object> {
|
||||
|
||||
return self.observer.listPublisher
|
||||
}
|
||||
|
||||
|
||||
// MARK: DynamicProperty
|
||||
|
||||
public mutating func update() {
|
||||
|
||||
self._observer.update()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@ObservedObject
|
||||
private var observer: Observer
|
||||
|
||||
|
||||
// MARK: - Observer
|
||||
|
||||
private final class Observer: ObservableObject {
|
||||
|
||||
@Published
|
||||
var items: Items
|
||||
|
||||
let listPublisher: ListPublisher<Object>
|
||||
|
||||
init(listPublisher: ListPublisher<Object>) {
|
||||
|
||||
self.listPublisher = listPublisher
|
||||
self.items = listPublisher.snapshot
|
||||
|
||||
listPublisher.addObserver(self) { [weak self] (listPublisher) in
|
||||
|
||||
guard let self = self else {
|
||||
|
||||
return
|
||||
}
|
||||
self.items = listPublisher.snapshot
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.listPublisher.removeObserver(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
110
Sources/LiveObject.swift
Normal file
110
Sources/LiveObject.swift
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// LiveObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 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(Combine) && canImport(SwiftUI)
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - LiveObject
|
||||
|
||||
@propertyWrapper
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
public struct LiveObject<O: DynamicObject>: DynamicProperty {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
public typealias Item = ObjectSnapshot<O>
|
||||
|
||||
public init(_ objectPublisher: ObjectPublisher<O>?) {
|
||||
|
||||
self.observer = .init(objectPublisher: objectPublisher)
|
||||
}
|
||||
|
||||
|
||||
// MARK: @propertyWrapper
|
||||
|
||||
public var wrappedValue: Item? {
|
||||
|
||||
return self.observer.item
|
||||
}
|
||||
|
||||
|
||||
// MARK: DynamicProperty
|
||||
|
||||
public mutating func update() {
|
||||
|
||||
self._observer.update()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@ObservedObject
|
||||
private var observer: Observer
|
||||
|
||||
|
||||
// MARK: - Observer
|
||||
|
||||
private final class Observer: ObservableObject {
|
||||
|
||||
@Published
|
||||
var item: Item?
|
||||
|
||||
let objectPublisher: ObjectPublisher<O>?
|
||||
|
||||
init(objectPublisher: ObjectPublisher<O>?) {
|
||||
|
||||
guard
|
||||
let dataStack = objectPublisher?.cs_dataStack(),
|
||||
let objectPublisher = objectPublisher?.asPublisher(in: dataStack)
|
||||
else {
|
||||
|
||||
self.objectPublisher = objectPublisher
|
||||
self.item = nil
|
||||
return
|
||||
}
|
||||
self.objectPublisher = objectPublisher
|
||||
self.item = objectPublisher.snapshot
|
||||
|
||||
objectPublisher.addObserver(self) { [weak self] (objectPublisher) in
|
||||
|
||||
guard let self = self else {
|
||||
|
||||
return
|
||||
}
|
||||
self.item = objectPublisher.snapshot
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.objectPublisher?.removeObserver(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -202,6 +202,11 @@ public final class ObjectPublisher<O: DynamicObject>: ObjectRepresentation, Hash
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal var cs_objectID: O.ObjectID {
|
||||
|
||||
return self.objectID()
|
||||
}
|
||||
|
||||
internal static func createUncached(objectID: O.ObjectID, context: NSManagedObjectContext) -> ObjectPublisher<O> {
|
||||
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
//
|
||||
// ListState.swift
|
||||
// ObjectReader.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Rommel Estropia on 2020/12/26.
|
||||
// Copyright © 2020 John Rommel Estropia. All rights reserved.
|
||||
// Copyright © 2021 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(Combine) && canImport(SwiftUI)
|
||||
@@ -15,40 +32,29 @@ import SwiftUI
|
||||
// MARK: - ObjectReader
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
public struct ObjectReader<Object: DynamicObject, Content: View, Placeholder: View>: View {
|
||||
public struct ObjectReader<Object: DynamicObject, Content: View, Value>: View {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
public init(
|
||||
_ objectPublisher: ObjectPublisher<Object>?,
|
||||
@ViewBuilder content: @escaping (ObjectSnapshot<Object>) -> Content,
|
||||
@ViewBuilder placeholder: @escaping () -> Placeholder
|
||||
) {
|
||||
@ViewBuilder content: @escaping (Value) -> Content
|
||||
) where Value == LiveObject<Object>.Item {
|
||||
|
||||
self.objectPublisher = .init(
|
||||
objectPublisher.flatMap {
|
||||
|
||||
guard let dataStack = $0.cs_dataStack() else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return $0.asPublisher(in: dataStack)
|
||||
}
|
||||
)
|
||||
self._object = .init(objectPublisher)
|
||||
self.content = content
|
||||
self.placeholder = placeholder
|
||||
self.keyPath = \.self
|
||||
}
|
||||
|
||||
public init(
|
||||
_ objectPublisher: ObjectPublisher<Object>?,
|
||||
@ViewBuilder content: @escaping (ObjectSnapshot<Object>) -> Content
|
||||
) where Placeholder == EmptyView {
|
||||
keyPath: KeyPath<LiveObject<Object>.Item, Value>,
|
||||
@ViewBuilder content: @escaping (Value) -> Content
|
||||
) {
|
||||
|
||||
self.init(
|
||||
objectPublisher,
|
||||
content: content,
|
||||
placeholder: EmptyView.init
|
||||
)
|
||||
self._object = .init(objectPublisher)
|
||||
self.content = content
|
||||
self.keyPath = keyPath
|
||||
}
|
||||
|
||||
|
||||
@@ -56,45 +62,20 @@ public struct ObjectReader<Object: DynamicObject, Content: View, Placeholder: Vi
|
||||
|
||||
public var body: some View {
|
||||
|
||||
if let snapshot = self.objectPublisher.wrappedValue?.snapshot {
|
||||
if let object = self.object {
|
||||
|
||||
self.content(snapshot)
|
||||
}
|
||||
else {
|
||||
|
||||
self.placeholder()
|
||||
self.content(object[keyPath: self.keyPath])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@ObservedObject
|
||||
private var objectPublisher: OptionalObservedObject<ObjectPublisher<Object>>
|
||||
@LiveObject
|
||||
private var object: LiveObject<Object>.Item?
|
||||
|
||||
private let content: (ObjectSnapshot<Object>) -> Content
|
||||
private let placeholder: () -> Placeholder
|
||||
|
||||
|
||||
// MARK: - OptionalObservedObject
|
||||
|
||||
fileprivate final class OptionalObservedObject<T: ObservableObject>: ObservableObject where ObservableObjectPublisher == T.ObjectWillChangePublisher {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
let wrappedValue: T?
|
||||
|
||||
init(_ wrappedValue: T?) {
|
||||
|
||||
self.wrappedValue = wrappedValue
|
||||
self.objectWillChange = wrappedValue.map(\.objectWillChange) ?? .init()
|
||||
}
|
||||
|
||||
// MARK: ObservableObject
|
||||
|
||||
let objectWillChange: ObservableObjectPublisher
|
||||
}
|
||||
private let content: (Value) -> Content
|
||||
private let keyPath: KeyPath<LiveObject<Object>.Item, Value>
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
65
Sources/SectionsReader.swift
Normal file
65
Sources/SectionsReader.swift
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// SectionsReader.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 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(Combine) && canImport(SwiftUI)
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
|
||||
// MARK: - SectionsReader
|
||||
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
public struct SectionsReader<Object: DynamicObject, Content: View>: View {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
public init(
|
||||
_ listPublisher: ListPublisher<Object>,
|
||||
@ViewBuilder content: @escaping (LiveList<Object>.Items) -> Content
|
||||
) {
|
||||
|
||||
self._list = .init(listPublisher)
|
||||
self.content = content
|
||||
}
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
public var body: some View {
|
||||
|
||||
self.content(self.list)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@LiveList
|
||||
private var list: LiveList<Object>.Items
|
||||
|
||||
private let content: (LiveList<Object>.Items) -> Content
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user