mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-15 05:33:31 +01:00
WIP: prototype for ManagedObjectProtocol
This commit is contained in:
@@ -413,13 +413,37 @@
|
||||
B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
|
||||
B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
|
||||
B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; };
|
||||
B5D339AF1E925BF200C880DE /* Prototype.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* Prototype.swift */; };
|
||||
B5D339B01E925BF200C880DE /* Prototype.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* Prototype.swift */; };
|
||||
B5D339B11E925BF200C880DE /* Prototype.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* Prototype.swift */; };
|
||||
B5D339B21E925BF200C880DE /* Prototype.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* Prototype.swift */; };
|
||||
B5D339AF1E925BF200C880DE /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* ObjectModel.swift */; };
|
||||
B5D339B01E925BF200C880DE /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* ObjectModel.swift */; };
|
||||
B5D339B11E925BF200C880DE /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* ObjectModel.swift */; };
|
||||
B5D339B21E925BF200C880DE /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339AE1E925BF200C880DE /* ObjectModel.swift */; };
|
||||
B5D339B41E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
|
||||
B5D339B51E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
|
||||
B5D339B61E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
|
||||
B5D339D81E9489AB00C880DE /* ManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339D71E9489AB00C880DE /* ManagedObject.swift */; };
|
||||
B5D339D91E9489AB00C880DE /* ManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339D71E9489AB00C880DE /* ManagedObject.swift */; };
|
||||
B5D339DA1E9489AB00C880DE /* ManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339D71E9489AB00C880DE /* ManagedObject.swift */; };
|
||||
B5D339DB1E9489AB00C880DE /* ManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339D71E9489AB00C880DE /* ManagedObject.swift */; };
|
||||
B5D339DD1E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339DC1E9489C700C880DE /* ManagedObjectProtocol.swift */; };
|
||||
B5D339DE1E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339DC1E9489C700C880DE /* ManagedObjectProtocol.swift */; };
|
||||
B5D339DF1E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339DC1E9489C700C880DE /* ManagedObjectProtocol.swift */; };
|
||||
B5D339E01E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339DC1E9489C700C880DE /* ManagedObjectProtocol.swift */; };
|
||||
B5D339E21E948C3600C880DE /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E11E948C3600C880DE /* Attribute.swift */; };
|
||||
B5D339E31E948C3600C880DE /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E11E948C3600C880DE /* Attribute.swift */; };
|
||||
B5D339E41E948C3600C880DE /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E11E948C3600C880DE /* Attribute.swift */; };
|
||||
B5D339E51E948C3600C880DE /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E11E948C3600C880DE /* Attribute.swift */; };
|
||||
B5D339E71E9493A500C880DE /* Entity.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E61E9493A500C880DE /* Entity.swift */; };
|
||||
B5D339E81E9493A500C880DE /* Entity.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E61E9493A500C880DE /* Entity.swift */; };
|
||||
B5D339E91E9493A500C880DE /* Entity.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E61E9493A500C880DE /* Entity.swift */; };
|
||||
B5D339EA1E9493A500C880DE /* Entity.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339E61E9493A500C880DE /* Entity.swift */; };
|
||||
B5D339EC1E9495E500C880DE /* Attribute+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339EB1E9495E500C880DE /* Attribute+Querying.swift */; };
|
||||
B5D339ED1E9495E500C880DE /* Attribute+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339EB1E9495E500C880DE /* Attribute+Querying.swift */; };
|
||||
B5D339EE1E9495E500C880DE /* Attribute+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339EB1E9495E500C880DE /* Attribute+Querying.swift */; };
|
||||
B5D339EF1E9495E500C880DE /* Attribute+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339EB1E9495E500C880DE /* Attribute+Querying.swift */; };
|
||||
B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */; };
|
||||
B5D339F21E94AF5800C880DE /* CoreStoreStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */; };
|
||||
B5D339F31E94AF5800C880DE /* CoreStoreStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */; };
|
||||
B5D339F41E94AF5800C880DE /* CoreStoreStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */; };
|
||||
B5D372841A39CD6900F583D9 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
|
||||
B5D39A0219FD00C9000E91BB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D39A0119FD00C9000E91BB /* Foundation.framework */; };
|
||||
B5D3F6451C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D3F6441C887C0A00C7492A /* LegacySQLiteStore.swift */; };
|
||||
@@ -700,8 +724,14 @@
|
||||
B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; };
|
||||
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreFetchedResultsController.swift; sourceTree = "<group>"; };
|
||||
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreError.swift; sourceTree = "<group>"; };
|
||||
B5D339AE1E925BF200C880DE /* Prototype.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prototype.swift; sourceTree = "<group>"; };
|
||||
B5D339AE1E925BF200C880DE /* ObjectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectModel.swift; sourceTree = "<group>"; };
|
||||
B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicModelTests.swift; sourceTree = "<group>"; };
|
||||
B5D339D71E9489AB00C880DE /* ManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedObject.swift; sourceTree = "<group>"; };
|
||||
B5D339DC1E9489C700C880DE /* ManagedObjectProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedObjectProtocol.swift; sourceTree = "<group>"; };
|
||||
B5D339E11E948C3600C880DE /* Attribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attribute.swift; sourceTree = "<group>"; };
|
||||
B5D339E61E9493A500C880DE /* Entity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Entity.swift; sourceTree = "<group>"; };
|
||||
B5D339EB1E9495E500C880DE /* Attribute+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Attribute+Querying.swift"; sourceTree = "<group>"; };
|
||||
B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreStrings.swift; sourceTree = "<group>"; };
|
||||
B5D372831A39CD6900F583D9 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
|
||||
B5D39A0119FD00C9000E91BB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
B5D3F6441C887C0A00C7492A /* LegacySQLiteStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacySQLiteStore.swift; sourceTree = "<group>"; };
|
||||
@@ -1051,7 +1081,11 @@
|
||||
B57358D71E5A7F9B0094B50A /* Dynamic Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5D339AE1E925BF200C880DE /* Prototype.swift */,
|
||||
B5D339E11E948C3600C880DE /* Attribute.swift */,
|
||||
B5D339D71E9489AB00C880DE /* ManagedObject.swift */,
|
||||
B5D339E61E9493A500C880DE /* Entity.swift */,
|
||||
B5D339DC1E9489C700C880DE /* ManagedObjectProtocol.swift */,
|
||||
B5D339AE1E925BF200C880DE /* ObjectModel.swift */,
|
||||
);
|
||||
path = "Dynamic Models";
|
||||
sourceTree = "<group>";
|
||||
@@ -1062,6 +1096,7 @@
|
||||
2F291E2619C6D3CF007AF63F /* CoreStore.swift */,
|
||||
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */,
|
||||
B549F6721E56A92800FBAB2D /* CoreDataNativeType.swift */,
|
||||
B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */,
|
||||
B5E84EDA1AFF84500064E85B /* Setup */,
|
||||
B5E84EE21AFF84610064E85B /* Logging */,
|
||||
B5E84EE91AFF846E0064E85B /* Transactions */,
|
||||
@@ -1178,6 +1213,7 @@
|
||||
B5E84EFD1AFF847B0064E85B /* Fetching and Querying */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5D339EB1E9495E500C880DE /* Attribute+Querying.swift */,
|
||||
B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */,
|
||||
B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */,
|
||||
B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */,
|
||||
@@ -1589,6 +1625,7 @@
|
||||
B529C2041CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */,
|
||||
B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */,
|
||||
B5E84F131AFF847B0064E85B /* Where.swift in Sources */,
|
||||
B5D339D81E9489AB00C880DE /* ManagedObject.swift in Sources */,
|
||||
B5D3F6451C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
|
||||
B596BBBB1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
@@ -1598,6 +1635,7 @@
|
||||
B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
|
||||
B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
|
||||
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
|
||||
B5D339E21E948C3600C880DE /* Attribute.swift in Sources */,
|
||||
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */,
|
||||
B53FBA0B1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
|
||||
B5E84F141AFF847B0064E85B /* DataStack+Querying.swift in Sources */,
|
||||
@@ -1608,6 +1646,7 @@
|
||||
B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B53FBA121CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5E1B5A81CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */,
|
||||
B5E1B59D1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */,
|
||||
B5ECDC231CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */,
|
||||
@@ -1656,18 +1695,20 @@
|
||||
B5E84F231AFF84860064E85B /* ListMonitor.swift in Sources */,
|
||||
B5E84EF71AFF846E0064E85B /* UnsafeDataTransaction.swift in Sources */,
|
||||
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */,
|
||||
B5D339DD1E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */,
|
||||
B5A5F2661CAEC50F004AB9AF /* CSSelect.swift in Sources */,
|
||||
B5ECDBE51CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
|
||||
B5519A4A1CA1F4FB002BEF78 /* CSError.swift in Sources */,
|
||||
B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */,
|
||||
B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */,
|
||||
B5D339EC1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
|
||||
B5E84F0F1AFF847B0064E85B /* From.swift in Sources */,
|
||||
B5FAD6A91B50A4B400714891 /* Progress+Convenience.swift in Sources */,
|
||||
B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */,
|
||||
B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
|
||||
B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */,
|
||||
B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */,
|
||||
B5D339AF1E925BF200C880DE /* Prototype.swift in Sources */,
|
||||
B5D339AF1E925BF200C880DE /* ObjectModel.swift in Sources */,
|
||||
B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
|
||||
B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
|
||||
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
|
||||
@@ -1696,6 +1737,7 @@
|
||||
B5E84EF41AFF846E0064E85B /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B5DBE2CD1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
|
||||
B546F95D1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B5D339E71E9493A500C880DE /* Entity.swift in Sources */,
|
||||
B5ECDC0B1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
|
||||
B5E84F151AFF847B0064E85B /* CoreStore+Querying.swift in Sources */,
|
||||
B5E84F241AFF84860064E85B /* ListObserver.swift in Sources */,
|
||||
@@ -1747,6 +1789,7 @@
|
||||
B529C2061CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */,
|
||||
82BA18AE1C4BBD3100A0916E /* DataStack+Transaction.swift in Sources */,
|
||||
82BA18AB1C4BBD3100A0916E /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B5D339D91E9489AB00C880DE /* ManagedObject.swift in Sources */,
|
||||
82BA18CE1C4BBD7100A0916E /* FetchedResultsControllerDelegate.swift in Sources */,
|
||||
B596BBBC1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
@@ -1756,6 +1799,7 @@
|
||||
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
|
||||
B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
|
||||
B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
|
||||
B5D339E31E948C3600C880DE /* Attribute.swift in Sources */,
|
||||
82BA18C51C4BBD5300A0916E /* ListObserver.swift in Sources */,
|
||||
B53FBA0D1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
|
||||
82BA18C21C4BBD5300A0916E /* ObjectMonitor.swift in Sources */,
|
||||
@@ -1766,6 +1810,7 @@
|
||||
B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5E1B5AA1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B5D339F21E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B5D3F6461C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
|
||||
B5E1B59F1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */,
|
||||
B5ECDC251CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */,
|
||||
@@ -1814,18 +1859,20 @@
|
||||
82BA18D11C4BBD7100A0916E /* NotificationObserver.swift in Sources */,
|
||||
82BA18BB1C4BBD4A00A0916E /* Where.swift in Sources */,
|
||||
B5A5F2681CAEC50F004AB9AF /* CSSelect.swift in Sources */,
|
||||
B5D339DE1E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */,
|
||||
B5ECDBE71CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
|
||||
B5519A4B1CA1F4FB002BEF78 /* CSError.swift in Sources */,
|
||||
82BA18D71C4BBD7100A0916E /* NSManagedObjectModel+Setup.swift in Sources */,
|
||||
82BA18C31C4BBD5300A0916E /* ObjectObserver.swift in Sources */,
|
||||
82BA18BF1C4BBD5300A0916E /* SectionBy.swift in Sources */,
|
||||
B5D339ED1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
|
||||
82BA18AC1C4BBD3100A0916E /* SynchronousDataTransaction.swift in Sources */,
|
||||
82BA18C71C4BBD5900A0916E /* CoreStore+Migration.swift in Sources */,
|
||||
B5E222251CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
|
||||
82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */,
|
||||
82BA18BA1C4BBD4A00A0916E /* Select.swift in Sources */,
|
||||
B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
|
||||
B5D339B01E925BF200C880DE /* Prototype.swift in Sources */,
|
||||
B5D339B01E925BF200C880DE /* ObjectModel.swift in Sources */,
|
||||
B5E2222C1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
|
||||
82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */,
|
||||
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */,
|
||||
@@ -1854,6 +1901,7 @@
|
||||
B5DBE2CE1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
|
||||
B546F95E1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B5ECDC0D1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
|
||||
B5D339E81E9493A500C880DE /* Entity.swift in Sources */,
|
||||
82BA18CC1C4BBD6400A0916E /* Progress+Convenience.swift in Sources */,
|
||||
82BA18C01C4BBD5300A0916E /* DataStack+Observing.swift in Sources */,
|
||||
82BA18A61C4BBD2900A0916E /* DefaultLogger.swift in Sources */,
|
||||
@@ -1905,6 +1953,7 @@
|
||||
B546F9761C9C553300D5AC55 /* SetupResult.swift in Sources */,
|
||||
B53FBA161CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5ECDC271CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */,
|
||||
B5D339DB1E9489AB00C880DE /* ManagedObject.swift in Sources */,
|
||||
B52DD1951BE1F92500949AFE /* CoreStoreError.swift in Sources */,
|
||||
B596BBBE1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
@@ -1914,6 +1963,7 @@
|
||||
B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
|
||||
B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
|
||||
B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */,
|
||||
B5D339E51E948C3600C880DE /* Attribute.swift in Sources */,
|
||||
B5A5F26A1CAEC50F004AB9AF /* CSSelect.swift in Sources */,
|
||||
B5220E1B1D13079B009BC71E /* CSCoreStore+Observing.swift in Sources */,
|
||||
B5FEC1911C9166E700532541 /* NSPersistentStore+Setup.swift in Sources */,
|
||||
@@ -1924,6 +1974,7 @@
|
||||
B5220E1C1D130801009BC71E /* FetchedResultsControllerDelegate.swift in Sources */,
|
||||
B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */,
|
||||
B5D339F41E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B5220E241D13085E009BC71E /* NSFetchedResultsController+Convenience.swift in Sources */,
|
||||
B559CD471CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
|
||||
B5ECDBF01CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
@@ -1972,18 +2023,20 @@
|
||||
B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */,
|
||||
B52DD1A41BE1F92F00949AFE /* ImportableObject.swift in Sources */,
|
||||
B5220E161D13067C009BC71E /* ObjectMonitor.swift in Sources */,
|
||||
B5D339E01E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */,
|
||||
B52DD1AE1BE1F93900949AFE /* OrderBy.swift in Sources */,
|
||||
B52DD1BA1BE1F94000949AFE /* MigrationChain.swift in Sources */,
|
||||
B50392FB1C479640009900CA /* NSManagedObject+Transaction.swift in Sources */,
|
||||
B52DD1A31BE1F92C00949AFE /* SaveResult.swift in Sources */,
|
||||
B5220E211D130816009BC71E /* CSObjectObserver.swift in Sources */,
|
||||
B5D339EF1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
|
||||
B52DD19F1BE1F92C00949AFE /* SynchronousDataTransaction.swift in Sources */,
|
||||
B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */,
|
||||
B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */,
|
||||
B5220E1A1D130791009BC71E /* CoreStoreFetchedResultsController.swift in Sources */,
|
||||
B53FBA0F1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
|
||||
B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */,
|
||||
B5D339B21E925BF200C880DE /* Prototype.swift in Sources */,
|
||||
B5D339B21E925BF200C880DE /* ObjectModel.swift in Sources */,
|
||||
B52DD19A1BE1F92800949AFE /* CoreStore+Logging.swift in Sources */,
|
||||
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */,
|
||||
B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
@@ -2012,6 +2065,7 @@
|
||||
B5DBE2D51C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
|
||||
B5AEFAB81C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
|
||||
B598514B1C90289F00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */,
|
||||
B5D339EA1E9493A500C880DE /* Entity.swift in Sources */,
|
||||
B52DD1AA1BE1F93500949AFE /* ClauseTypes.swift in Sources */,
|
||||
B53FBA021CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
|
||||
B51FE5AF1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
|
||||
@@ -2063,6 +2117,7 @@
|
||||
B529C2071CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */,
|
||||
B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */,
|
||||
B56321961BD65216006C9394 /* From.swift in Sources */,
|
||||
B5D339DA1E9489AB00C880DE /* ManagedObject.swift in Sources */,
|
||||
B5ECDC021CA80CBA00C7F112 /* CSWhere.swift in Sources */,
|
||||
B596BBBD1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
|
||||
B5ECDC081CA8138100C7F112 /* CSOrderBy.swift in Sources */,
|
||||
@@ -2072,6 +2127,7 @@
|
||||
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
|
||||
B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
|
||||
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
|
||||
B5D339E41E948C3600C880DE /* Attribute.swift in Sources */,
|
||||
B53FBA0E1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
|
||||
B563219E1BD65216006C9394 /* CoreStore+Observing.swift in Sources */,
|
||||
B5D7A5B91CA3BF8F005C752B /* CSInto.swift in Sources */,
|
||||
@@ -2082,6 +2138,7 @@
|
||||
B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B5D3F6471C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
|
||||
B5D339F31E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B5E1B5A01CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */,
|
||||
B5ECDC261CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */,
|
||||
B563217F1BD65216006C9394 /* CoreStore.swift in Sources */,
|
||||
@@ -2130,18 +2187,20 @@
|
||||
B563219A1BD65216006C9394 /* GroupBy.swift in Sources */,
|
||||
B5ECDBE81CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
|
||||
B5A5F2691CAEC50F004AB9AF /* CSSelect.swift in Sources */,
|
||||
B5D339DF1E9489C700C880DE /* ManagedObjectProtocol.swift in Sources */,
|
||||
B5519A4C1CA1F4FB002BEF78 /* CSError.swift in Sources */,
|
||||
B563219B1BD65216006C9394 /* Tweak.swift in Sources */,
|
||||
B56321B51BD6521C006C9394 /* NSManagedObjectModel+Setup.swift in Sources */,
|
||||
B563218F1BD65216006C9394 /* ImportableObject.swift in Sources */,
|
||||
B56321991BD65216006C9394 /* OrderBy.swift in Sources */,
|
||||
B5D339EE1E9495E500C880DE /* Attribute+Querying.swift in Sources */,
|
||||
B56321A51BD65216006C9394 /* MigrationChain.swift in Sources */,
|
||||
B563218E1BD65216006C9394 /* SaveResult.swift in Sources */,
|
||||
B5E222261CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
|
||||
B56321A21BD65216006C9394 /* ListObserver.swift in Sources */,
|
||||
B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */,
|
||||
B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
|
||||
B5D339B11E925BF200C880DE /* Prototype.swift in Sources */,
|
||||
B5D339B11E925BF200C880DE /* ObjectModel.swift in Sources */,
|
||||
B5E2222D1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
|
||||
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
|
||||
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */,
|
||||
@@ -2170,6 +2229,7 @@
|
||||
B5DBE2CF1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
|
||||
B546F95F1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B5ECDC0E1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
|
||||
B5D339E91E9493A500C880DE /* Entity.swift in Sources */,
|
||||
B56321A41BD65216006C9394 /* CoreStore+Migration.swift in Sources */,
|
||||
B56321A01BD65216006C9394 /* ObjectObserver.swift in Sources */,
|
||||
B56321951BD65216006C9394 /* ClauseTypes.swift in Sources */,
|
||||
|
||||
@@ -37,7 +37,7 @@ class BaseTestCase: XCTestCase {
|
||||
|
||||
@nonobjc
|
||||
@discardableResult
|
||||
func prepareStack<T>(configurations: [String?] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
||||
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
|
||||
@@ -28,7 +28,7 @@ class BaseTestDataTestCase: BaseTestCase {
|
||||
}()
|
||||
|
||||
@nonobjc
|
||||
func prepareTestDataForStack(_ stack: DataStack, configurations: [String?] = [nil]) {
|
||||
func prepareTestDataForStack(_ stack: DataStack, configurations: [ModelConfiguration] = [nil]) {
|
||||
|
||||
try! stack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
@@ -13,7 +13,7 @@ import CoreData
|
||||
@testable import CoreStore
|
||||
|
||||
|
||||
class Bird: CoreStoreManagedObject {
|
||||
class Bird: ManagedObject {
|
||||
|
||||
let species = Attribute.Required<String>("species", default: "Swift")
|
||||
}
|
||||
@@ -28,10 +28,8 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
|
||||
func testDynamicModels_CanBeDeclaredCorrectly() {
|
||||
|
||||
let birdEntity = Entity<Bird>("Bird")
|
||||
let mascotEntity = Entity<Mascot>("Mascot")
|
||||
let dataStack = DataStack(
|
||||
dynamicModel: ModelVersion(
|
||||
dynamicModel: ObjectModel(
|
||||
version: "V1",
|
||||
entities: [
|
||||
Entity<Bird>("Bird"),
|
||||
@@ -54,14 +52,14 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let bird = Bird(transaction.create(Into<NSManagedObject>(birdEntity.dynamicClass)))
|
||||
let bird = transaction.create(Into<Bird>())
|
||||
XCTAssertEqual(bird.species*, "Swift")
|
||||
XCTAssertTrue(type(of: bird.species*) == String.self)
|
||||
|
||||
bird.species .= "Sparrow"
|
||||
XCTAssertEqual(bird.species*, "Sparrow")
|
||||
|
||||
let mascot = Mascot(transaction.create(Into<NSManagedObject>(mascotEntity.dynamicClass)))
|
||||
let mascot = transaction.create(Into<Mascot>())
|
||||
XCTAssertEqual(mascot.species*, "Swift")
|
||||
XCTAssertEqual(mascot.nickname*, nil)
|
||||
|
||||
@@ -83,20 +81,16 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
let p1 = Bird.where({ $0.species == "Sparrow" })
|
||||
XCTAssertEqual(p1.predicate, Where("%K == %@", "species", "Sparrow").predicate)
|
||||
|
||||
let rawBird = transaction.fetchOne(From<NSManagedObject>(birdEntity.dynamicClass), p1)
|
||||
XCTAssertNotNil(rawBird)
|
||||
|
||||
let bird = Bird(rawBird)
|
||||
XCTAssertEqual(bird.species*, "Sparrow")
|
||||
let bird = transaction.fetchOne(From<Bird>())
|
||||
XCTAssertNotNil(bird)
|
||||
XCTAssertEqual(bird!.species*, "Sparrow")
|
||||
|
||||
let p2 = Mascot.where({ $0.nickname == "Riko" })
|
||||
XCTAssertEqual(p2.predicate, Where("%K == %@", "nickname", "Riko").predicate)
|
||||
|
||||
let rawMascot = transaction.fetchOne(From<NSManagedObject>(mascotEntity.dynamicClass), p2)
|
||||
XCTAssertNotNil(rawMascot)
|
||||
|
||||
let mascot = Mascot(rawMascot)
|
||||
XCTAssertEqual(mascot.nickname*, "Riko")
|
||||
let mascot = transaction.fetchOne(From<Mascot>())
|
||||
XCTAssertNotNil(mascot)
|
||||
XCTAssertEqual(mascot!.nickname*, "Riko")
|
||||
|
||||
let p3 = Mascot.where({ $0.year == 2016 })
|
||||
XCTAssertEqual(p3.predicate, Where("%K == %@", "year", 2016).predicate)
|
||||
@@ -116,7 +110,7 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
func prepareStack(_ dataStack: DataStack, configurations: [String?] = [nil], _ closure: (_ dataStack: DataStack) -> Void) {
|
||||
func prepareStack(_ dataStack: DataStack, configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> Void) {
|
||||
|
||||
do {
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacksAndTransactions_CanFetchOneExisting() {
|
||||
|
||||
let configurations: [String?] = ["Config1"]
|
||||
let configurations: [ModelConfiguration] = ["Config1"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -139,7 +139,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacksAndTransactions_CanFetchAllExisting() {
|
||||
|
||||
let configurations: [String?] = ["Config1"]
|
||||
let configurations: [ModelConfiguration] = ["Config1"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -274,7 +274,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchOneFromDefaultConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -413,7 +413,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchOneFromSingleConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -596,7 +596,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchOneFromMultipleConfigurations() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -739,7 +739,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchAllFromDefaultConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -948,7 +948,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchAllFromSingleConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1185,7 +1185,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchAllFromMultipleConfigurations() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1384,7 +1384,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchCountFromDefaultConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1507,7 +1507,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchCountFromSingleConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1666,7 +1666,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchCountFromMultipleConfigurations() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1785,7 +1785,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchOneFromDefaultConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1932,7 +1932,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchOneFromSingleConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -2126,7 +2126,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchOneFromMultipleConfigurations() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -2277,7 +2277,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchAllFromDefaultConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -2494,7 +2494,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchAllFromSingleConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -2754,7 +2754,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchAllFromMultipleConfigurations() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -2973,7 +2973,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchCountFromDefaultConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -3104,7 +3104,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchCountFromSingleConfiguration() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -3274,7 +3274,7 @@ final class FetchTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatTransactions_CanFetchCountFromMultipleConfigurations() {
|
||||
|
||||
let configurations: [String?] = [nil, "Config1", "Config2"]
|
||||
let configurations: [ModelConfiguration] = [nil, "Config1", "Config2"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
|
||||
@@ -38,7 +38,7 @@ final class FromTests: BaseTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let from = From()
|
||||
let from = From<NSManagedObject>()
|
||||
XCTAssert(from.entityClass === NSManagedObject.self)
|
||||
XCTAssertNil(from.configurations)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ final class IntoTests: XCTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatIntoClauseConstants_AreCorrect() {
|
||||
|
||||
XCTAssertEqual(Into<NSManagedObject>.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
|
||||
XCTAssertEqual(DataStack.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -44,7 +44,7 @@ final class IntoTests: XCTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let into = Into()
|
||||
let into = Into<NSManagedObject>()
|
||||
XCTAssert(into.entityClass === NSManagedObject.self)
|
||||
XCTAssertNil(into.configuration)
|
||||
XCTAssertTrue(into.inferStoreIfPossible)
|
||||
@@ -58,14 +58,7 @@ final class IntoTests: XCTestCase {
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
XCTAssert(into.entityClass === TestEntity1.self)
|
||||
XCTAssertNil(into.configuration)
|
||||
XCTAssertTrue(into.inferStoreIfPossible)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let into = Into(TestEntity1.self)
|
||||
XCTAssert(into.entityClass === TestEntity1.self)
|
||||
XCTAssertNil(into.configuration)
|
||||
XCTAssertTrue(into.inferStoreIfPossible)
|
||||
@@ -84,13 +77,6 @@ final class IntoTests: XCTestCase {
|
||||
XCTAssertEqual(into.configuration, "Config1")
|
||||
XCTAssertFalse(into.inferStoreIfPossible)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
||||
XCTAssert(into.entityClass === TestEntity1.self)
|
||||
XCTAssertEqual(into.configuration, "Config1")
|
||||
XCTAssertFalse(into.inferStoreIfPossible)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -98,43 +84,30 @@ final class IntoTests: XCTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let into = Into()
|
||||
XCTAssertEqual(into, Into())
|
||||
let into = Into<NSManagedObject>()
|
||||
XCTAssertEqual(into, Into<NSManagedObject>())
|
||||
XCTAssertEqual(into, Into(NSManagedObject.self as AnyClass))
|
||||
XCTAssertFalse(into == Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(NSManagedObject.self))
|
||||
XCTAssertNotEqual(into, Into<NSManagedObject>(TestEntity1.self))
|
||||
XCTAssertNotEqual(into, Into<NSManagedObject>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
XCTAssertEqual(into, Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
|
||||
XCTAssertFalse(into == Into<TestEntity2>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
XCTAssertEqual(into, Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
|
||||
XCTAssertFalse(into == Into<TestEntity2>())
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let into = Into(TestEntity1.self)
|
||||
XCTAssert(into == Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self))
|
||||
XCTAssertFalse(into == Into<TestEntity2>())
|
||||
XCTAssertFalse(into == Into<TestEntity1>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>("Config1")
|
||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass, "Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||
}
|
||||
do {
|
||||
@@ -142,16 +115,14 @@ final class IntoTests: XCTestCase {
|
||||
let into = Into(TestEntity1.self, "Config1")
|
||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
||||
XCTAssert(into == Into<TestEntity1>("Config1"))
|
||||
let into = Into(TestEntity1.self, "Config1")
|
||||
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity1>("Config2"))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,45 +131,9 @@ final class IntoTests: XCTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let into = Into()
|
||||
let into = Into<NSManagedObject>()
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>("Config1")
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self, "Config1")
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAttributeValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -220,7 +220,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAverageValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -399,7 +399,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryCountValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -576,7 +576,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryMaximumValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -760,7 +760,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryMinimumValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -944,7 +944,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQuerySumValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1122,7 +1122,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryObjectIDValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1290,7 +1290,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAttributes() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1344,7 +1344,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAggregates() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
|
||||
66
Sources/CoreStoreStrings.swift
Normal file
66
Sources/CoreStoreStrings.swift
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// CoreStoreStrings.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - XcdatamodelFilename
|
||||
|
||||
/**
|
||||
A `String` that pertains to the name of an *.xcdatamodeld file (without the file extension).
|
||||
*/
|
||||
public typealias XcdatamodelFilename = String
|
||||
|
||||
|
||||
// MARK: - ModelConfiguration
|
||||
|
||||
/**
|
||||
An `Optional<String>` that pertains to the name of a "Configuration" which particular groups of entities may belong to. When `nil`, pertains to the default configuration which includes all entities.
|
||||
*/
|
||||
public typealias ModelConfiguration = String?
|
||||
|
||||
|
||||
// MARK: - ModelVersion
|
||||
|
||||
/**
|
||||
An `String` that pertains to the name of a versioned *.xcdatamodeld file (without the file extension).
|
||||
*/
|
||||
public typealias ModelVersion = String
|
||||
|
||||
|
||||
// MARK: - EntityName
|
||||
|
||||
/**
|
||||
An `String` that pertains to an Entity name.
|
||||
*/
|
||||
public typealias EntityName = String
|
||||
|
||||
|
||||
// MARK: - ClassName
|
||||
|
||||
/**
|
||||
An `String` that pertains to a dynamically-accessable class name (usable with NSClassFromString(...)).
|
||||
*/
|
||||
public typealias ClassName = String
|
||||
69
Sources/Fetching and Querying/Attribute+Querying.swift
Normal file
69
Sources/Fetching and Querying/Attribute+Querying.swift
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Attribute+Querying.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - AttributeContainer.Required
|
||||
|
||||
public extension AttributeContainer.Required where V: CVarArg {
|
||||
|
||||
public static func == (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
public static func < (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K < %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func > (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K > %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func <= (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K <= %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func >= (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func != (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K != %@", attribute.keyPath, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - AttributeContainer.Optional
|
||||
|
||||
public extension AttributeContainer.Optional where V: CVarArg {
|
||||
|
||||
public static func == (_ attribute: AttributeContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public func fetchOne<T: ManagedObjectProtocol>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -137,7 +137,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public func fetchOne<T: ManagedObjectProtocol>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
|
||||
@@ -39,18 +39,18 @@ import CoreData
|
||||
let person = transaction.fetchOne(From<MyPersonEntity>("Configuration1"))
|
||||
```
|
||||
*/
|
||||
public struct From<T: NSManagedObject> {
|
||||
public struct From<T: ManagedObjectProtocol> {
|
||||
|
||||
/**
|
||||
The associated `NSManagedObject` entity class
|
||||
The associated `NSManagedObject` or `ManagedObject` entity class
|
||||
*/
|
||||
public let entityClass: AnyClass
|
||||
public let entityClass: T.Type
|
||||
|
||||
/**
|
||||
The `NSPersistentStore` configuration names to associate objects from.
|
||||
May contain `String`s to pertain to named configurations, or `nil` to pertain to the default configuration
|
||||
*/
|
||||
public let configurations: [String?]?
|
||||
public let configurations: [ModelConfiguration]?
|
||||
|
||||
/**
|
||||
Initializes a `From` clause.
|
||||
@@ -68,38 +68,22 @@ public struct From<T: NSManagedObject> {
|
||||
```
|
||||
let people = transaction.fetchAll(From<MyPersonEntity>())
|
||||
```
|
||||
- parameter entity: the associated `NSManagedObject` type
|
||||
- parameter entity: the associated `NSManagedObject` or `ManagedObject` type
|
||||
*/
|
||||
public init(_ entity: T.Type) {
|
||||
|
||||
self.init(entityClass: entity, configurations: nil)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `From` clause with the specified entity class.
|
||||
```
|
||||
let people = transaction.fetchAll(From<MyPersonEntity>())
|
||||
```
|
||||
- parameter entityClass: the associated `NSManagedObject` entity class
|
||||
*/
|
||||
public init(_ entityClass: AnyClass) {
|
||||
|
||||
CoreStore.assert(
|
||||
entityClass is T.Type,
|
||||
"Attempted to create generic type \(cs_typeName(From<T>.self)) with entity class \(cs_typeName(entityClass))"
|
||||
)
|
||||
self.init(entityClass: entityClass, configurations: nil)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `From` clause with the specified configurations.
|
||||
```
|
||||
let people = transaction.fetchAll(From<MyPersonEntity>(nil, "Configuration1"))
|
||||
```
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `ManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter otherConfigurations: an optional list of other configuration names to associate objects from (see `configuration` parameter)
|
||||
*/
|
||||
public init(_ configuration: String?, _ otherConfigurations: String?...) {
|
||||
public init(_ configuration: ModelConfiguration, _ otherConfigurations: ModelConfiguration...) {
|
||||
|
||||
self.init(entityClass: T.self, configurations: [configuration] + otherConfigurations)
|
||||
}
|
||||
@@ -109,9 +93,9 @@ public struct From<T: NSManagedObject> {
|
||||
```
|
||||
let people = transaction.fetchAll(From<MyPersonEntity>(["Configuration1", "Configuration2"]))
|
||||
```
|
||||
- parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `ManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ configurations: [String?]) {
|
||||
public init(_ configurations: [ModelConfiguration]) {
|
||||
|
||||
self.init(entityClass: T.self, configurations: configurations)
|
||||
}
|
||||
@@ -121,11 +105,11 @@ public struct From<T: NSManagedObject> {
|
||||
```
|
||||
let people = transaction.fetchAll(From(MyPersonEntity.self, nil, "Configuration1"))
|
||||
```
|
||||
- parameter entity: the associated `NSManagedObject` type
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter entity: the associated `NSManagedObject` or `ManagedObject` type
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `ManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter otherConfigurations: an optional list of other configuration names to associate objects from (see `configuration` parameter)
|
||||
*/
|
||||
public init(_ entity: T.Type, _ configuration: String?, _ otherConfigurations: String?...) {
|
||||
public init(_ entity: T.Type, _ configuration: ModelConfiguration, _ otherConfigurations: ModelConfiguration...) {
|
||||
|
||||
self.init(entityClass: entity, configurations: [configuration] + otherConfigurations)
|
||||
}
|
||||
@@ -135,55 +119,29 @@ public struct From<T: NSManagedObject> {
|
||||
```
|
||||
let people = transaction.fetchAll(From(MyPersonEntity.self, ["Configuration1", "Configuration1"]))
|
||||
```
|
||||
- parameter entity: the associated `NSManagedObject` type
|
||||
- parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter entity: the associated `NSManagedObject` or `ManagedObject` type
|
||||
- parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `ManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ entity: T.Type, _ configurations: [String?]) {
|
||||
public init(_ entity: T.Type, _ configurations: [ModelConfiguration]) {
|
||||
|
||||
self.init(entityClass: entity, configurations: configurations)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `From` clause with the specified configurations.
|
||||
```
|
||||
let people = transaction.fetchAll(From(MyPersonEntity.self, nil, "Configuration1"))
|
||||
```
|
||||
- parameter entity: the associated `NSManagedObject` entity class
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
- parameter otherConfigurations: an optional list of other configuration names to associate objects from (see `configuration` parameter)
|
||||
*/
|
||||
public init(_ entityClass: AnyClass, _ configuration: String?, _ otherConfigurations: String?...) {
|
||||
|
||||
CoreStore.assert(
|
||||
entityClass is T.Type,
|
||||
"Attempted to create generic type \(cs_typeName(From<T>.self)) with entity class \(cs_typeName(entityClass))"
|
||||
)
|
||||
self.init(entityClass: entityClass, configurations: [configuration] + otherConfigurations)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `From` clause with the specified configurations.
|
||||
```
|
||||
let people = transaction.fetchAll(From(MyPersonEntity.self, ["Configuration1", "Configuration1"]))
|
||||
```
|
||||
- parameter entity: the associated `NSManagedObject` entity class
|
||||
- parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ entityClass: AnyClass, _ configurations: [String?]) {
|
||||
|
||||
CoreStore.assert(
|
||||
entityClass is T.Type,
|
||||
"Attempted to create generic type \(cs_typeName(From<T>.self)) with entity class \(cs_typeName(entityClass))"
|
||||
)
|
||||
self.init(entityClass: entityClass, configurations: configurations)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let findPersistentStores: (_ context: NSManagedObjectContext) -> [NSPersistentStore]?
|
||||
|
||||
internal init(entityClass: T.Type, configurations: [ModelConfiguration]?, findPersistentStores: @escaping (_ context: NSManagedObjectContext) -> [NSPersistentStore]?) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configurations = configurations
|
||||
self.findPersistentStores = findPersistentStores
|
||||
}
|
||||
|
||||
internal func applyToFetchRequest<ResultType: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<ResultType>, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool {
|
||||
|
||||
fetchRequest.entity = context.entityDescriptionForEntityClass(self.entityClass)
|
||||
fetchRequest.entity = context.parentStack!.entityDescription(for: EntityIdentifier(self.entityClass))!
|
||||
guard applyAffectedStores else {
|
||||
|
||||
return true
|
||||
@@ -206,30 +164,21 @@ public struct From<T: NSManagedObject> {
|
||||
return stores?.isEmpty == false
|
||||
}
|
||||
|
||||
internal func downcast() -> From<NSManagedObject> {
|
||||
|
||||
return From<NSManagedObject>(
|
||||
entityClass: self.entityClass,
|
||||
configurations: self.configurations,
|
||||
findPersistentStores: self.findPersistentStores
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let findPersistentStores: (_ context: NSManagedObjectContext) -> [NSPersistentStore]?
|
||||
|
||||
private init(entityClass: AnyClass, configurations: [String?]?) {
|
||||
private init(entityClass: T.Type, configurations: [ModelConfiguration]?) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configurations = configurations
|
||||
|
||||
let entityIdentifier = EntityIdentifier(entityClass)
|
||||
if let configurations = configurations {
|
||||
|
||||
let configurationsSet = Set(configurations.map { $0 ?? Into.defaultConfigurationName })
|
||||
let configurationsSet = Set(configurations.map({ $0 ?? DataStack.defaultConfigurationName }))
|
||||
self.findPersistentStores = { (context: NSManagedObjectContext) -> [NSPersistentStore]? in
|
||||
|
||||
return context.parentStack?.persistentStoresForEntityClass(entityClass)?.filter {
|
||||
return context.parentStack?.persistentStores(for: entityIdentifier)?.filter {
|
||||
|
||||
return configurationsSet.contains($0.configurationName)
|
||||
}
|
||||
@@ -239,15 +188,8 @@ public struct From<T: NSManagedObject> {
|
||||
|
||||
self.findPersistentStores = { (context: NSManagedObjectContext) -> [NSPersistentStore]? in
|
||||
|
||||
return context.parentStack?.persistentStoresForEntityClass(entityClass)
|
||||
return context.parentStack?.persistentStores(for: entityIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private init(entityClass: AnyClass, configurations: [String?]?, findPersistentStores: @escaping (_ context: NSManagedObjectContext) -> [NSPersistentStore]?) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configurations = configurations
|
||||
self.findPersistentStores = findPersistentStores
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
@@ -111,7 +110,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try sourceArray.flatMap { (source) -> T? in
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
@@ -145,7 +144,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
let entityType = into.entityClass
|
||||
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
|
||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||
|
||||
@@ -198,7 +197,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
let entityType = into.entityClass
|
||||
var importSourceByID = Dictionary<T.UniqueIDType, T.ImportSource>()
|
||||
let sortedIDs = try autoreleasepool {
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
}
|
||||
else {
|
||||
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap(From.init) else {
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap({ From<T>($0 as! T.Type) }) else {
|
||||
|
||||
CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From<T>.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
|
||||
}
|
||||
|
||||
@@ -54,25 +54,6 @@ internal extension NSManagedObjectContext {
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func entityDescriptionForEntityType(_ entity: NSManagedObject.Type) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescriptionForEntityClass(entity)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func entityDescriptionForEntityClass(_ entity: AnyClass) -> NSEntityDescription? {
|
||||
|
||||
guard let entityName = self.parentStack?.entityNameForEntityClass(entity) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return NSEntityDescription.entity(
|
||||
forEntityName: entityName,
|
||||
in: self
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func setupForCoreStoreWithContextName(_ contextName: String) {
|
||||
|
||||
|
||||
@@ -95,14 +95,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
public func fetchOne<T: ManagedObjectProtocol>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
return self.fetchOne(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public func fetchOne<T: ManagedObjectProtocol>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -116,6 +115,7 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
return nil
|
||||
}
|
||||
return self.fetchOne(fetchRequest.dynamicCast())
|
||||
.flatMap(from.entityClass.cs_from)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
|
||||
@@ -157,22 +157,50 @@ internal extension NSManagedObjectModel {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func entityNameForClass(_ entityClass: AnyClass) -> String {
|
||||
internal var entityDescriptionsByEntityIdentifier: [EntityIdentifier: NSEntityDescription] {
|
||||
|
||||
return self.entityNameMapping[NSStringFromClass(entityClass)]!
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func entityTypesMapping() -> [String: NSManagedObject.Type] {
|
||||
|
||||
var mapping = [String: NSManagedObject.Type]()
|
||||
self.entityNameMapping.forEach { (className, entityName) in
|
||||
if let mapping: NSDictionary = cs_getAssociatedObjectForKey(&PropertyKeys.objectClassNamesByEntityName, inObject: self) {
|
||||
|
||||
mapping[entityName] = (NSClassFromString(className)! as! NSManagedObject.Type)
|
||||
return mapping as! [EntityIdentifier: NSEntityDescription]
|
||||
}
|
||||
|
||||
var mapping: [EntityIdentifier: NSEntityDescription] = [:]
|
||||
self.entities.forEach { (entityDescription) in
|
||||
|
||||
let entityIdentifier = EntityIdentifier(entityDescription)
|
||||
mapping[entityIdentifier] = entityDescription
|
||||
}
|
||||
cs_setAssociatedCopiedObject(
|
||||
mapping as NSDictionary,
|
||||
forKey: &PropertyKeys.objectClassNamesByEntityName,
|
||||
inObject: self
|
||||
)
|
||||
return mapping
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
// @nonobjc
|
||||
// internal func entityNames(for type: NSManagedObject.Type) -> Set<EntityName> {
|
||||
//
|
||||
// let className = NSStringFromClass(type)
|
||||
// return Set(
|
||||
// self.objectClassNamesByEntityName
|
||||
// .filter({ $0.value == className })
|
||||
// .map({ $0.key })
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// @nonobjc
|
||||
// internal func entityTypesMapping() -> [EntityName: NSManagedObject.Type] {
|
||||
//
|
||||
// var mapping = [EntityName: NSManagedObject.Type]()
|
||||
// self.objectClassNamesByEntityName.forEach { (entityName, className) in
|
||||
//
|
||||
// mapping[entityName] = (NSClassFromString(className)! as! NSManagedObject.Type)
|
||||
// }
|
||||
// return mapping
|
||||
// }
|
||||
|
||||
@nonobjc
|
||||
internal func mergedModels() -> [NSManagedObjectModel] {
|
||||
|
||||
@@ -256,39 +284,9 @@ internal extension NSManagedObjectModel {
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
private var entityNameMapping: [String: String] {
|
||||
|
||||
get {
|
||||
|
||||
if let mapping: NSDictionary = cs_getAssociatedObjectForKey(&PropertyKeys.entityNameMapping, inObject: self) {
|
||||
|
||||
return mapping as! [String: String]
|
||||
}
|
||||
|
||||
var mapping = [String: String]()
|
||||
self.entities.forEach { // TODO: use AnyEntity as mapping key
|
||||
|
||||
guard let entityName = $0.name else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let className = $0.managedObjectClassName
|
||||
mapping[className!] = entityName
|
||||
}
|
||||
cs_setAssociatedCopiedObject(
|
||||
mapping as NSDictionary,
|
||||
forKey: &PropertyKeys.entityNameMapping,
|
||||
inObject: self
|
||||
)
|
||||
return mapping
|
||||
}
|
||||
}
|
||||
|
||||
private struct PropertyKeys {
|
||||
|
||||
static var entityNameMapping: Void?
|
||||
static var objectClassNamesByEntityName: Void?
|
||||
|
||||
static var modelVersionFileURL: Void?
|
||||
static var modelVersions: Void?
|
||||
|
||||
@@ -72,7 +72,7 @@ internal extension NSPersistentStoreCoordinator {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func addPersistentStoreSynchronously(_ storeType: String, configuration: String?, URL storeURL: URL?, options: [NSObject : AnyObject]?) throws -> NSPersistentStore {
|
||||
internal func addPersistentStoreSynchronously(_ storeType: String, configuration: ModelConfiguration, URL storeURL: URL?, options: [NSObject : AnyObject]?) throws -> NSPersistentStore {
|
||||
|
||||
var store: NSPersistentStore?
|
||||
var storeError: NSError?
|
||||
|
||||
@@ -44,21 +44,9 @@ public extension CSCoreStore {
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
@objc
|
||||
public static var entityClassesByName: [String: NSManagedObject.Type] {
|
||||
public static func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return CoreStore.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the `defaultStack`'s model.
|
||||
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@objc
|
||||
public static func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
|
||||
|
||||
return CoreStore.entityTypesByName[name]
|
||||
return CoreStore.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,4 +125,30 @@ public extension CSCoreStore {
|
||||
|
||||
return self.defaultStack.addSQLiteStorageAndWait(storage, error: error)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public static var entityClassesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return CoreStore.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the `defaultStack`'s model.
|
||||
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public static func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
|
||||
|
||||
return CoreStore.entityTypesByName[name]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(modelName: String?, bundle: Bundle?, versionChain: [String]?) {
|
||||
public convenience init(modelName: XcdatamodelFilename?, bundle: Bundle?, versionChain: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
@@ -73,7 +73,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(modelName: String?, bundle: Bundle?, versionTree: [String: String]?) {
|
||||
public convenience init(modelName: XcdatamodelFilename?, bundle: Bundle?, versionTree: [String: String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
@@ -128,23 +128,12 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the stack's model.
|
||||
Returns the entity name-to-class type mapping from the `CSDataStack`'s model.
|
||||
*/
|
||||
@objc
|
||||
public var entityClassesByName: [String: NSManagedObject.Type] {
|
||||
public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the stack's's model.
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@objc
|
||||
public func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName[name]
|
||||
return self.bridgeToSwift.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,6 +257,31 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
self.bridgeToSwift = swiftValue
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the stack's model.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public var entityClassesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the stack's's model.
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName[name]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `From`
|
||||
*/
|
||||
@objc
|
||||
public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
public final class CSFrom: NSObject {
|
||||
|
||||
/**
|
||||
The associated `NSManagedObject` entity class
|
||||
@@ -71,7 +71,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass) {
|
||||
public convenience init(entityClass: NSManagedObject.Type) {
|
||||
|
||||
self.init(From(entityClass))
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass, configuration: Any) {
|
||||
public convenience init(entityClass: NSManagedObject.Type, configuration: Any) {
|
||||
|
||||
switch configuration {
|
||||
|
||||
@@ -111,9 +111,9 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass, configurations: [Any]) {
|
||||
public convenience init(entityClass: NSManagedObject.Type, configurations: [Any]) {
|
||||
|
||||
var arguments = [String?]()
|
||||
var arguments = [ModelConfiguration]()
|
||||
for configuration in configurations {
|
||||
|
||||
switch configuration {
|
||||
@@ -154,7 +154,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - From
|
||||
|
||||
extension From: CoreStoreSwiftType {
|
||||
extension From where T: NSManagedObject {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -162,4 +162,16 @@ extension From: CoreStoreSwiftType {
|
||||
|
||||
return CSFrom(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate func downcast() -> From<NSManagedObject> {
|
||||
|
||||
return From<NSManagedObject>(
|
||||
entityClass: self.entityClass,
|
||||
configurations: self.configurations,
|
||||
findPersistentStores: self.findPersistentStores
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(configuration: String?) {
|
||||
public convenience init(configuration: ModelConfiguration) {
|
||||
|
||||
self.init(InMemoryStore(configuration: configuration))
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
|
||||
The configuration name in the model file
|
||||
*/
|
||||
@objc
|
||||
public var configuration: String? {
|
||||
public var configuration: ModelConfiguration {
|
||||
|
||||
return self.bridgeToSwift.configuration
|
||||
}
|
||||
|
||||
@@ -35,13 +35,13 @@ import CoreData
|
||||
- SeeAlso: `Into`
|
||||
*/
|
||||
@objc
|
||||
public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
public final class CSInto: NSObject {
|
||||
|
||||
/**
|
||||
The associated `NSManagedObject` entity class
|
||||
*/
|
||||
@objc
|
||||
public var entityClass: AnyClass {
|
||||
public var entityClass: NSManagedObject.Type {
|
||||
|
||||
return self.bridgeToSwift.entityClass
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
|
||||
*/
|
||||
@objc
|
||||
public var configuration: String? {
|
||||
public var configuration: ModelConfiguration {
|
||||
|
||||
return self.bridgeToSwift.configuration
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass) {
|
||||
public convenience init(entityClass: NSManagedObject.Type) {
|
||||
|
||||
self.init(Into(entityClass))
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass, configuration: String?) {
|
||||
public convenience init(entityClass: NSManagedObject.Type, configuration: ModelConfiguration) {
|
||||
|
||||
self.init(Into(entityClass, configuration))
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - Into
|
||||
|
||||
extension Into: CoreStoreSwiftType {
|
||||
extension Into where T: NSManagedObject {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -130,4 +130,16 @@ extension Into: CoreStoreSwiftType {
|
||||
|
||||
return CSInto(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate func downcast() -> Into<NSManagedObject> {
|
||||
|
||||
return Into<NSManagedObject>(
|
||||
entityClass: self.entityClass,
|
||||
configuration: self.configuration,
|
||||
inferStoreIfPossible: self.inferStoreIfPossible
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(fileURL: URL, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
|
||||
self.init(
|
||||
SQLiteStore(
|
||||
@@ -68,7 +68,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(fileName: String, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
|
||||
self.init(
|
||||
SQLiteStore(
|
||||
@@ -133,7 +133,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
public var configuration: String? {
|
||||
public var configuration: ModelConfiguration {
|
||||
|
||||
return self.bridgeToSwift.configuration
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public protocol CSStorageInterface {
|
||||
The configuration name in the model file
|
||||
*/
|
||||
@objc
|
||||
var configuration: String? { get }
|
||||
var configuration: ModelConfiguration { get }
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`
|
||||
|
||||
@@ -88,7 +88,7 @@ fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: CS
|
||||
let controller = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: CoreStoreFetchRequest().dynamicCast(),
|
||||
from: from?.bridgeToSwift.downcast(),
|
||||
from: from?.bridgeToSwift,
|
||||
sectionBy: sectionBy?.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
|
||||
@@ -42,9 +42,17 @@ public extension CoreStore {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
public static var entityTypesByName: [String: NSManagedObject.Type] {
|
||||
public static func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.defaultStack.entityTypesByName
|
||||
return self.defaultStack.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
public static func entityTypesByName(for type: ManagedObject.Type) -> [EntityName: ManagedObject.Type] {
|
||||
|
||||
return self.defaultStack.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +63,14 @@ public extension CoreStore {
|
||||
return self.defaultStack.entityDescription(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `ManagedObject` subclass from `defaultStack`'s model.
|
||||
*/
|
||||
public static func entityDescription(for type: ManagedObject.Type) -> NSEntityDescription? {
|
||||
|
||||
return self.defaultStack.entityDescription(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an `SQLiteStore` with default parameters and adds it to the `defaultStack`. This method blocks until completion.
|
||||
```
|
||||
@@ -155,6 +171,18 @@ public extension CoreStore {
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new CoreStore.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
|
||||
public static var entityTypesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.defaultStack.entityTypesByName
|
||||
}
|
||||
|
||||
|
||||
// MARK: Obsolete
|
||||
|
||||
@available(*, obsoleted: 3.0.0, renamed: "entityDescription(for:)")
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class DataStack: Equatable {
|
||||
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
|
||||
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
public convenience init(modelName: String = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
|
||||
public convenience init(modelName: XcdatamodelFilename = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
|
||||
|
||||
let model = NSManagedObjectModel.fromBundle(
|
||||
bundle,
|
||||
@@ -51,12 +51,12 @@ public final class DataStack: Equatable {
|
||||
self.init(model: model, migrationChain: migrationChain)
|
||||
}
|
||||
|
||||
public convenience init(dynamicModel: ModelVersion) {
|
||||
public convenience init(dynamicModel: ObjectModel) {
|
||||
|
||||
self.init(model: dynamicModel.createModel())
|
||||
}
|
||||
|
||||
public convenience init(dynamicModels: [ModelVersion], migrationChain: MigrationChain = nil) {
|
||||
public convenience init(dynamicModels: [ObjectModel], migrationChain: MigrationChain = nil) {
|
||||
|
||||
CoreStore.assert(
|
||||
migrationChain.valid,
|
||||
@@ -106,9 +106,49 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public var entityTypesByName: [String: NSManagedObject.Type] {
|
||||
public func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.model.entityTypesMapping()
|
||||
var entityTypesByName: [EntityName: NSManagedObject.Type] = [:]
|
||||
for (entityIdentifier, entityDescription) in self.model.entityDescriptionsByEntityIdentifier {
|
||||
|
||||
switch entityIdentifier.category {
|
||||
|
||||
case .coreData:
|
||||
let actualType = NSClassFromString(entityDescription.managedObjectClassName!)! as! NSManagedObject.Type
|
||||
if (actualType as AnyClass).isSubclass(of: type) {
|
||||
|
||||
entityTypesByName[entityDescription.name!] = actualType
|
||||
}
|
||||
|
||||
case .coreStore:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public func entityTypesByName(for type: ManagedObject.Type) -> [EntityName: ManagedObject.Type] {
|
||||
|
||||
var entityTypesByName: [EntityName: ManagedObject.Type] = [:]
|
||||
for (entityIdentifier, entityDescription) in self.model.entityDescriptionsByEntityIdentifier {
|
||||
|
||||
switch entityIdentifier.category {
|
||||
|
||||
case .coreData:
|
||||
continue
|
||||
|
||||
case .coreStore:
|
||||
let actualType = NSClassFromString(entityDescription.managedObjectClassName!)! as! ManagedObject.Type
|
||||
if (actualType as AnyClass).isSubclass(of: type) {
|
||||
|
||||
entityTypesByName[entityDescription.name!] = actualType
|
||||
}
|
||||
}
|
||||
}
|
||||
return entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,10 +156,15 @@ public final class DataStack: Equatable {
|
||||
*/
|
||||
public func entityDescription(for type: NSManagedObject.Type) -> NSEntityDescription? {
|
||||
|
||||
return NSEntityDescription.entity(
|
||||
forEntityName: self.model.entityNameForClass(type),
|
||||
in: self.mainContext
|
||||
)
|
||||
return self.entityDescription(for: EntityIdentifier(type))
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `ManagedObject` subclass.
|
||||
*/
|
||||
public func entityDescription(for type: ManagedObject.Type) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescription(for: EntityIdentifier(type))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,6 +453,8 @@ public final class DataStack: Equatable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal static var defaultConfigurationName = "PF_DEFAULT_CONFIGURATION_NAME"
|
||||
|
||||
internal static let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData"
|
||||
|
||||
internal let coordinator: NSPersistentStoreCoordinator
|
||||
@@ -434,34 +481,27 @@ public final class DataStack: Equatable {
|
||||
.first
|
||||
}
|
||||
|
||||
internal func entityNameForEntityClass(_ entityClass: AnyClass) -> String? {
|
||||
|
||||
return self.model.entityNameForClass(entityClass)
|
||||
}
|
||||
|
||||
internal func persistentStoresForEntityClass(_ entityClass: AnyClass) -> [NSPersistentStore]? {
|
||||
internal func persistentStores(for entityIdentifier: EntityIdentifier) -> [NSPersistentStore]? {
|
||||
|
||||
var returnValue: [NSPersistentStore]? = nil
|
||||
self.storeMetadataUpdateQueue.sync(flags: .barrier) {
|
||||
|
||||
returnValue = self.entityConfigurationsMapping[NSStringFromClass(entityClass)]?.map {
|
||||
|
||||
return self.configurationStoreMapping[$0]!
|
||||
} ?? []
|
||||
returnValue = self.finalConfigurationsByEntityIdentifier[entityIdentifier]?
|
||||
.map({ self.persistentStoresByFinalConfiguration[$0]! }) ?? []
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
internal func persistentStoreForEntityClass(_ entityClass: AnyClass, configuration: String?, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
internal func persistentStore(for entityIdentifier: EntityIdentifier, configuration: ModelConfiguration, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
|
||||
return self.storeMetadataUpdateQueue.sync(flags: .barrier) { () -> (store: NSPersistentStore?, isAmbiguous: Bool) in
|
||||
|
||||
let configurationsForEntity = self.entityConfigurationsMapping[NSStringFromClass(entityClass)] ?? []
|
||||
let configurationsForEntity = self.finalConfigurationsByEntityIdentifier[entityIdentifier] ?? []
|
||||
if let configuration = configuration {
|
||||
|
||||
if configurationsForEntity.contains(configuration) {
|
||||
|
||||
return (store: self.configurationStoreMapping[configuration], isAmbiguous: false)
|
||||
return (store: self.persistentStoresByFinalConfiguration[configuration], isAmbiguous: false)
|
||||
}
|
||||
else if !inferStoreIfPossible {
|
||||
|
||||
@@ -475,7 +515,7 @@ public final class DataStack: Equatable {
|
||||
return (store: nil, isAmbiguous: false)
|
||||
|
||||
case 1 where inferStoreIfPossible:
|
||||
return (store: self.configurationStoreMapping[configurationsForEntity.first!], isAmbiguous: false)
|
||||
return (store: self.persistentStoresByFinalConfiguration[configurationsForEntity.first!], isAmbiguous: false)
|
||||
|
||||
default:
|
||||
return (store: nil, isAmbiguous: true)
|
||||
@@ -496,7 +536,7 @@ public final class DataStack: Equatable {
|
||||
self.storeMetadataUpdateQueue.async(flags: .barrier) {
|
||||
|
||||
let configurationName = persistentStore.configurationName
|
||||
self.configurationStoreMapping[configurationName] = persistentStore
|
||||
self.persistentStoresByFinalConfiguration[configurationName] = persistentStore
|
||||
for entityDescription in (self.coordinator.managedObjectModel.entities(forConfigurationName: configurationName) ?? []) {
|
||||
|
||||
let managedObjectClassName = entityDescription.managedObjectClassName!
|
||||
@@ -504,18 +544,23 @@ public final class DataStack: Equatable {
|
||||
NSClassFromString(managedObjectClassName) != nil,
|
||||
"The class \(cs_typeName(managedObjectClassName)) for the entity \(cs_typeName(entityDescription.name)) does not exist. Check if the subclass type and module name are properly configured."
|
||||
)
|
||||
|
||||
if self.entityConfigurationsMapping[managedObjectClassName] == nil {
|
||||
let entityIdentifier = EntityIdentifier(entityDescription)
|
||||
if self.finalConfigurationsByEntityIdentifier[entityIdentifier] == nil {
|
||||
|
||||
self.entityConfigurationsMapping[managedObjectClassName] = []
|
||||
self.finalConfigurationsByEntityIdentifier[entityIdentifier] = []
|
||||
}
|
||||
self.entityConfigurationsMapping[managedObjectClassName]?.insert(configurationName)
|
||||
self.finalConfigurationsByEntityIdentifier[entityIdentifier]?.insert(configurationName)
|
||||
}
|
||||
}
|
||||
storage.didAddToDataStack(self)
|
||||
return persistentStore
|
||||
}
|
||||
|
||||
internal func entityDescription(for entityIdentifier: EntityIdentifier) -> NSEntityDescription? {
|
||||
|
||||
return self.model.entityDescriptionsByEntityIdentifier[entityIdentifier]
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@@ -526,8 +571,8 @@ public final class DataStack: Equatable {
|
||||
// return true
|
||||
// }()
|
||||
|
||||
private var configurationStoreMapping = [String: NSPersistentStore]()
|
||||
private var entityConfigurationsMapping = [String: Set<String>]() // TODO: change key to AnyEntity
|
||||
private var persistentStoresByFinalConfiguration = [String: NSPersistentStore]()
|
||||
private var finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set<String>]()
|
||||
|
||||
deinit {
|
||||
|
||||
@@ -545,6 +590,18 @@ public final class DataStack: Equatable {
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new DataStack.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
|
||||
public var entityTypesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.entityTypesByName(for: NSManagedObject.self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Obsolete
|
||||
|
||||
@available(*, obsoleted: 3.0.0, renamed: "entityDescription(for:)")
|
||||
|
||||
166
Sources/Setup/Dynamic Models/Attribute.swift
Normal file
166
Sources/Setup/Dynamic Models/Attribute.swift
Normal file
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// Attribute.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
postfix operator *
|
||||
|
||||
|
||||
// MARK: - AttributeContainer
|
||||
|
||||
public enum AttributeContainer<O: ManagedObjectProtocol> {
|
||||
|
||||
// MARK: - Required
|
||||
|
||||
public final class Required<V: ImportableAttributeType>: AttributeProtocol {
|
||||
|
||||
public static func .= (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
public static postfix func * (_ attribute: AttributeContainer<O>.Required<V>) -> V {
|
||||
|
||||
return attribute.value
|
||||
}
|
||||
|
||||
public let keyPath: String
|
||||
|
||||
public init(_ keyPath: String, `default`: V = V.cs_emptyValue()) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.defaultValue = `default`.cs_toImportableNativeType()
|
||||
}
|
||||
|
||||
public var value: V {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
let value = object.value(forKey: key)! as! V.ImportableNativeType
|
||||
return V.cs_fromImportableNativeType(value)!
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
object.setValue(newValue.cs_toImportableNativeType(), forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal static var attributeType: NSAttributeType {
|
||||
|
||||
return V.cs_rawAttributeType
|
||||
}
|
||||
|
||||
internal let defaultValue: Any?
|
||||
internal let isOptional = false
|
||||
|
||||
internal var accessRawObject: () -> NSManagedObject = {
|
||||
|
||||
fatalError("\(O.self) property values should not be accessed")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Optional
|
||||
|
||||
public final class Optional<V: ImportableAttributeType>: AttributeProtocol {
|
||||
|
||||
public static func .= (_ attribute: AttributeContainer<O>.Optional<V>, _ value: V?) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
public static postfix func * (_ attribute: AttributeContainer<O>.Optional<V>) -> V? {
|
||||
|
||||
return attribute.value
|
||||
}
|
||||
|
||||
public let keyPath: String
|
||||
|
||||
public init(_ keyPath: String, `default`: V? = nil) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.defaultValue = `default`?.cs_toImportableNativeType()
|
||||
}
|
||||
|
||||
public var value: V? {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
guard let value = object.value(forKey: key) as! V.ImportableNativeType? else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return V.cs_fromImportableNativeType(value)
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
object.setValue(newValue?.cs_toImportableNativeType(), forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal static var attributeType: NSAttributeType {
|
||||
|
||||
return V.cs_rawAttributeType
|
||||
}
|
||||
|
||||
internal let defaultValue: Any?
|
||||
internal let isOptional = true
|
||||
internal var accessRawObject: () -> NSManagedObject = {
|
||||
|
||||
fatalError("\(O.self) property values should not be accessed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - AttributeProtocol
|
||||
|
||||
internal protocol AttributeProtocol: class {
|
||||
|
||||
static var attributeType: NSAttributeType { get }
|
||||
|
||||
var keyPath: String { get }
|
||||
var isOptional: Bool { get }
|
||||
var defaultValue: Any? { get }
|
||||
var accessRawObject: () -> NSManagedObject { get set }
|
||||
}
|
||||
198
Sources/Setup/Dynamic Models/Entity.swift
Normal file
198
Sources/Setup/Dynamic Models/Entity.swift
Normal file
@@ -0,0 +1,198 @@
|
||||
//
|
||||
// Entity.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
import ObjectiveC
|
||||
|
||||
|
||||
// MARK: - EntityProtocol
|
||||
|
||||
public protocol EntityProtocol {
|
||||
|
||||
var entityDescription: NSEntityDescription { get }
|
||||
}
|
||||
|
||||
|
||||
// MARK: Entity
|
||||
|
||||
public struct Entity<O: ManagedObject>: EntityProtocol {
|
||||
|
||||
public let entityDescription: NSEntityDescription
|
||||
internal var dynamicClass: AnyClass {
|
||||
|
||||
return NSClassFromString(self.entityDescription.managedObjectClassName!)!
|
||||
}
|
||||
|
||||
public init(_ entityName: String) {
|
||||
|
||||
let dynamicClassName = String(reflecting: O.self)
|
||||
.appending("__\(entityName)")
|
||||
.replacingOccurrences(of: ".", with: "_")
|
||||
.replacingOccurrences(of: "<", with: "_")
|
||||
.replacingOccurrences(of: ">", with: "_")
|
||||
// TODO: assign entityName through ModelVersion and
|
||||
// TODO: set NSEntityDescription.userInfo AnyEntity
|
||||
let newClass: AnyClass?
|
||||
|
||||
if NSClassFromString(dynamicClassName) == nil {
|
||||
|
||||
newClass = objc_allocateClassPair(NSManagedObject.self, dynamicClassName, 0)
|
||||
}
|
||||
else {
|
||||
|
||||
newClass = nil
|
||||
}
|
||||
|
||||
defer {
|
||||
|
||||
if let newClass = newClass {
|
||||
|
||||
objc_registerClassPair(newClass)
|
||||
}
|
||||
}
|
||||
|
||||
let entityDescription = NSEntityDescription()
|
||||
entityDescription.userInfo = [
|
||||
EntityIdentifier.UserInfoKey.CoreStoreManagedObjectName: String(reflecting: O.self)
|
||||
]
|
||||
entityDescription.name = entityName
|
||||
entityDescription.managedObjectClassName = NSStringFromClass(NSManagedObject.self)
|
||||
// entityDescription.managedObjectClassName = dynamicClassName // TODO: return to NSManagedObject
|
||||
entityDescription.properties = type(of: self).initializeAttributes(Mirror(reflecting: O.meta))
|
||||
|
||||
self.entityDescription = entityDescription
|
||||
}
|
||||
|
||||
private static func initializeAttributes(_ mirror: Mirror) -> [NSAttributeDescription] {
|
||||
|
||||
var attributeDescriptions: [NSAttributeDescription] = []
|
||||
for child in mirror.children {
|
||||
|
||||
guard case let property as AttributeProtocol = child.value else {
|
||||
|
||||
continue
|
||||
}
|
||||
let attributeDescription = NSAttributeDescription()
|
||||
attributeDescription.name = property.keyPath
|
||||
attributeDescription.attributeType = type(of: property).attributeType
|
||||
attributeDescription.isOptional = property.isOptional
|
||||
attributeDescription.defaultValue = property.defaultValue
|
||||
attributeDescriptions.append(attributeDescription)
|
||||
}
|
||||
if let baseEntityAttributeDescriptions = mirror.superclassMirror.flatMap(self.initializeAttributes) {
|
||||
|
||||
attributeDescriptions.append(contentsOf: baseEntityAttributeDescriptions)
|
||||
}
|
||||
return attributeDescriptions
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - EntityIdentifier
|
||||
|
||||
internal struct EntityIdentifier: Hashable {
|
||||
|
||||
// MARK: - Category
|
||||
|
||||
internal enum Category: Int {
|
||||
|
||||
case coreData
|
||||
case coreStore
|
||||
}
|
||||
|
||||
|
||||
// MARK: -
|
||||
|
||||
internal let category: Category
|
||||
internal let interfacedClassName: String
|
||||
|
||||
internal init(_ type: NSManagedObject.Type) {
|
||||
|
||||
self.category = .coreData
|
||||
self.interfacedClassName = String(reflecting: type)
|
||||
}
|
||||
|
||||
internal init(_ type: ManagedObject.Type) {
|
||||
|
||||
self.category = .coreStore
|
||||
self.interfacedClassName = String(reflecting: type)
|
||||
}
|
||||
|
||||
internal init(_ type: ManagedObjectProtocol.Type) {
|
||||
|
||||
switch type {
|
||||
|
||||
case let type as NSManagedObject.Type:
|
||||
self.init(type)
|
||||
|
||||
case let type as ManagedObject.Type:
|
||||
self.init(type)
|
||||
|
||||
default:
|
||||
CoreStore.abort("\(cs_typeName(ManagedObjectProtocol.self)) is not meant to be implemented by external types.")
|
||||
}
|
||||
}
|
||||
|
||||
internal init(_ entityDescription: NSEntityDescription) {
|
||||
|
||||
if let coreStoreManagedObjectName = entityDescription.userInfo?[EntityIdentifier.UserInfoKey.CoreStoreManagedObjectName] as! String? {
|
||||
|
||||
self.category = .coreStore
|
||||
self.interfacedClassName = coreStoreManagedObjectName
|
||||
}
|
||||
else {
|
||||
|
||||
self.category = .coreData
|
||||
self.interfacedClassName = entityDescription.managedObjectClassName!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
static func == (lhs: EntityIdentifier, rhs: EntityIdentifier) -> Bool {
|
||||
|
||||
return lhs.category == rhs.category
|
||||
&& lhs.interfacedClassName == rhs.interfacedClassName
|
||||
}
|
||||
|
||||
|
||||
// MARK: Hashable
|
||||
|
||||
var hashValue: Int {
|
||||
|
||||
return self.category.hashValue
|
||||
^ self.interfacedClassName.hashValue
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate enum UserInfoKey {
|
||||
|
||||
fileprivate static let CoreStoreManagedObjectName = "CoreStoreManagedObjectName"
|
||||
}
|
||||
}
|
||||
68
Sources/Setup/Dynamic Models/ManagedObject.swift
Normal file
68
Sources/Setup/Dynamic Models/ManagedObject.swift
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// ManagedObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - ManagedObject
|
||||
|
||||
open class ManagedObject: ManagedObjectProtocol {
|
||||
|
||||
public required init(_ object: NSManagedObject) {
|
||||
|
||||
self.isMeta = false
|
||||
self.rawObject = object
|
||||
self.initializeAttributes(Mirror(reflecting: self), { [unowned object] in object })
|
||||
}
|
||||
|
||||
public required init(asMeta: Void) {
|
||||
|
||||
self.isMeta = true
|
||||
self.rawObject = nil
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let rawObject: NSManagedObject?
|
||||
internal let isMeta: Bool
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func initializeAttributes(_ mirror: Mirror, _ accessRawObject: @escaping () -> NSManagedObject) {
|
||||
|
||||
_ = mirror.superclassMirror.flatMap({ self.initializeAttributes($0, accessRawObject) })
|
||||
for child in mirror.children {
|
||||
|
||||
guard case let property as AttributeProtocol = child.value else {
|
||||
|
||||
continue
|
||||
}
|
||||
property.accessRawObject = accessRawObject
|
||||
}
|
||||
}
|
||||
}
|
||||
119
Sources/Setup/Dynamic Models/ManagedObjectProtocol.swift
Normal file
119
Sources/Setup/Dynamic Models/ManagedObjectProtocol.swift
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// ManagedObjectProtocol.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - ManagedObjectProtocol
|
||||
|
||||
public protocol ManagedObjectProtocol: class {
|
||||
|
||||
static func cs_forceCreate(entityDescription: NSEntityDescription, into context: NSManagedObjectContext, assignTo store: NSPersistentStore) -> Self
|
||||
|
||||
static func cs_from(object: NSManagedObject) -> Self
|
||||
}
|
||||
|
||||
public extension ManagedObjectProtocol where Self: ManagedObject {
|
||||
|
||||
public typealias Attribute = AttributeContainer<Self>
|
||||
|
||||
@inline(__always)
|
||||
public static func keyPath<O: ManagedObject, V: ImportableAttributeType>(_ attribute: (Self) -> AttributeContainer<O>.Required<V>) -> String {
|
||||
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func keyPath<O: ManagedObject, V: ImportableAttributeType>(_ attribute: (Self) -> AttributeContainer<O>.Optional<V>) -> String {
|
||||
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func `where`(_ condition: (Self) -> Where) -> Where {
|
||||
|
||||
return condition(self.meta)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal static var meta: Self {
|
||||
|
||||
return self.init(asMeta: ())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - NSManagedObject
|
||||
|
||||
extension NSManagedObject: ManagedObjectProtocol {
|
||||
|
||||
// MARK: ManagedObjectProtocol
|
||||
|
||||
public static func cs_from(object: NSManagedObject) -> Self {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSManagedObject>(_ value: Any) -> T {
|
||||
|
||||
return value as! T
|
||||
}
|
||||
return forceCast(object)
|
||||
}
|
||||
|
||||
public static func cs_forceCreate(entityDescription: NSEntityDescription, into context: NSManagedObjectContext, assignTo store: NSPersistentStore) -> Self {
|
||||
|
||||
let object = self.init(entity: entityDescription, insertInto: context)
|
||||
defer {
|
||||
|
||||
context.assign(object, to: store)
|
||||
}
|
||||
return object
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ManagedObject
|
||||
|
||||
extension ManagedObject {
|
||||
|
||||
// MARK: ManagedObjectProtocol
|
||||
|
||||
public static func cs_from(object: NSManagedObject) -> Self {
|
||||
|
||||
return self.init(object)
|
||||
}
|
||||
|
||||
public static func cs_forceCreate(entityDescription: NSEntityDescription, into context: NSManagedObjectContext, assignTo store: NSPersistentStore) -> Self {
|
||||
|
||||
let type = NSClassFromString(entityDescription.managedObjectClassName!)! as! NSManagedObject.Type
|
||||
let object = type.init(entity: entityDescription, insertInto: context)
|
||||
defer {
|
||||
|
||||
context.assign(object, to: store)
|
||||
}
|
||||
return self.init(object)
|
||||
}
|
||||
}
|
||||
76
Sources/Setup/Dynamic Models/ObjectModel.swift
Normal file
76
Sources/Setup/Dynamic Models/ObjectModel.swift
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// ObjectModel.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 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.
|
||||
//
|
||||
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - ObjectModel
|
||||
|
||||
public final class ObjectModel {
|
||||
|
||||
public let version: String
|
||||
|
||||
public convenience init(version: String, entities: [EntityProtocol]) {
|
||||
|
||||
self.init(version: version, configurationEntities: [DataStack.defaultConfigurationName: entities])
|
||||
}
|
||||
|
||||
public required init(version: String, configurationEntities: [String: [EntityProtocol]]) {
|
||||
|
||||
self.version = version
|
||||
|
||||
var entityConfigurations: [String: Set<NSEntityDescription>] = [:]
|
||||
for (configuration, entities) in configurationEntities {
|
||||
|
||||
entityConfigurations[configuration] = Set(entities.map({ $0.entityDescription }))
|
||||
}
|
||||
let allEntities = Set(entityConfigurations.map({ $0.value }).joined())
|
||||
entityConfigurations[DataStack.defaultConfigurationName] = allEntities
|
||||
|
||||
self.entityConfigurations = entityConfigurations
|
||||
self.entities = allEntities
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let entities: Set<NSEntityDescription>
|
||||
internal let entityConfigurations: [String: Set<NSEntityDescription>]
|
||||
|
||||
internal func createModel() -> NSManagedObjectModel {
|
||||
|
||||
let model = NSManagedObjectModel()
|
||||
model.entities = self.entities.sorted(by: { $0.name! < $1.name! })
|
||||
for (configuration, entities) in self.entityConfigurations {
|
||||
|
||||
model.setEntities(
|
||||
entities.sorted(by: { $0.name! < $1.name! }),
|
||||
forConfigurationName: configuration
|
||||
)
|
||||
}
|
||||
return model
|
||||
}
|
||||
}
|
||||
@@ -1,324 +0,0 @@
|
||||
//
|
||||
// Prototype.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Estropia on 2017/04/03.
|
||||
// Copyright © 2017 John Rommel Estropia. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
import ObjectiveC
|
||||
|
||||
|
||||
public protocol ManagedObjectProtocol: class {}
|
||||
|
||||
public protocol EntityProtocol {
|
||||
|
||||
var entityDescription: NSEntityDescription { get }
|
||||
}
|
||||
|
||||
internal protocol AttributeProtocol: class {
|
||||
|
||||
static var attributeType: NSAttributeType { get }
|
||||
var keyPath: String { get }
|
||||
var defaultValue: Any? { get }
|
||||
var accessRawObject: () -> NSManagedObject { get set }
|
||||
}
|
||||
|
||||
open class CoreStoreManagedObject: ManagedObjectProtocol {
|
||||
|
||||
internal let rawObject: NSManagedObject?
|
||||
internal let isMeta: Bool
|
||||
|
||||
public required init(_ object: NSManagedObject?) {
|
||||
|
||||
self.isMeta = object == nil
|
||||
self.rawObject = object
|
||||
|
||||
guard let object = object else {
|
||||
|
||||
return
|
||||
}
|
||||
self.initializeAttributes(Mirror(reflecting: self), { [unowned object] in object })
|
||||
}
|
||||
|
||||
private func initializeAttributes(_ mirror: Mirror, _ accessRawObject: @escaping () -> NSManagedObject) {
|
||||
|
||||
_ = mirror.superclassMirror.flatMap({ self.initializeAttributes($0, accessRawObject) })
|
||||
for child in mirror.children {
|
||||
|
||||
guard case let property as AttributeProtocol = child.value else {
|
||||
|
||||
continue
|
||||
}
|
||||
property.accessRawObject = accessRawObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Entity<O: CoreStoreManagedObject>: EntityProtocol {
|
||||
|
||||
public let entityDescription: NSEntityDescription
|
||||
internal var dynamicClass: AnyClass {
|
||||
|
||||
return NSClassFromString(self.entityDescription.managedObjectClassName!)!
|
||||
}
|
||||
|
||||
public init(_ entityName: String) {
|
||||
|
||||
let dynamicClassName = String(reflecting: O.self)
|
||||
.appending("__\(entityName)")
|
||||
.replacingOccurrences(of: ".", with: "_")
|
||||
.replacingOccurrences(of: "<", with: "_")
|
||||
.replacingOccurrences(of: ">", with: "_")
|
||||
// TODO: assign entityName through ModelVersion and
|
||||
// TODO: set NSEntityDescription.userInfo AnyEntity
|
||||
let newClass: AnyClass?
|
||||
|
||||
if NSClassFromString(dynamicClassName) == nil {
|
||||
|
||||
newClass = objc_allocateClassPair(NSManagedObject.self, dynamicClassName, 0)
|
||||
}
|
||||
else {
|
||||
|
||||
newClass = nil
|
||||
}
|
||||
|
||||
defer {
|
||||
|
||||
if let newClass = newClass {
|
||||
|
||||
objc_registerClassPair(newClass)
|
||||
}
|
||||
}
|
||||
|
||||
let entityDescription = NSEntityDescription()
|
||||
entityDescription.name = entityName
|
||||
entityDescription.managedObjectClassName = dynamicClassName // TODO: return to NSManagedObject
|
||||
entityDescription.properties = type(of: self).initializeAttributes(Mirror(reflecting: O.meta))
|
||||
|
||||
self.entityDescription = entityDescription
|
||||
}
|
||||
|
||||
private static func initializeAttributes(_ mirror: Mirror) -> [NSAttributeDescription] {
|
||||
|
||||
var attributeDescriptions: [NSAttributeDescription] = []
|
||||
for child in mirror.children {
|
||||
|
||||
guard case let property as AttributeProtocol = child.value else {
|
||||
|
||||
continue
|
||||
}
|
||||
let attributeDescription = NSAttributeDescription()
|
||||
attributeDescription.name = property.keyPath
|
||||
attributeDescription.attributeType = type(of: property).attributeType
|
||||
attributeDescription.isOptional = false
|
||||
attributeDescription.defaultValue = property.defaultValue
|
||||
attributeDescriptions.append(attributeDescription)
|
||||
}
|
||||
if let baseEntityAttributeDescriptions = mirror.superclassMirror.flatMap(self.initializeAttributes) {
|
||||
|
||||
attributeDescriptions.append(contentsOf: baseEntityAttributeDescriptions)
|
||||
}
|
||||
return attributeDescriptions
|
||||
}
|
||||
}
|
||||
|
||||
public enum AttributeContainer<O: ManagedObjectProtocol> {
|
||||
|
||||
public final class Required<V: ImportableAttributeType>: AttributeProtocol {
|
||||
|
||||
static var attributeType: NSAttributeType { return V.cs_rawAttributeType }
|
||||
|
||||
let keyPath: String
|
||||
let defaultValue: Any?
|
||||
var accessRawObject: () -> NSManagedObject = { fatalError("\(O.self) property values should not be accessed") }
|
||||
|
||||
var value: V {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
let value = object.value(forKey: key)! as! V.ImportableNativeType
|
||||
return V.cs_fromImportableNativeType(value)!
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
object.setValue(newValue.cs_toImportableNativeType(), forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
public init(_ keyPath: String, `default`: V = V.cs_emptyValue()) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.defaultValue = `default`
|
||||
}
|
||||
}
|
||||
|
||||
public final class Optional<V: ImportableAttributeType>: AttributeProtocol {
|
||||
|
||||
static var attributeType: NSAttributeType { return V.cs_rawAttributeType }
|
||||
|
||||
let keyPath: String
|
||||
let defaultValue: Any?
|
||||
var accessRawObject: () -> NSManagedObject = { fatalError("\(O.self) property values should not be accessed") }
|
||||
|
||||
var value: V? {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
guard let value = object.value(forKey: key) as! V.ImportableNativeType? else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return V.cs_fromImportableNativeType(value)
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.accessRawObject()
|
||||
let key = self.keyPath
|
||||
object.setValue(newValue?.cs_toImportableNativeType(), forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
public init(_ keyPath: String, `default`: V? = nil) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.defaultValue = `default`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension ManagedObjectProtocol where Self: CoreStoreManagedObject {
|
||||
|
||||
public typealias Attribute = AttributeContainer<Self>
|
||||
|
||||
internal static var meta: Self {
|
||||
|
||||
return self.init(nil)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func keyPath<O: CoreStoreManagedObject, V: ImportableAttributeType>(_ attribute: (Self) -> AttributeContainer<O>.Required<V>) -> String {
|
||||
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func keyPath<O: CoreStoreManagedObject, V: ImportableAttributeType>(_ attribute: (Self) -> AttributeContainer<O>.Optional<V>) -> String {
|
||||
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func `where`(_ condition: (Self) -> Where) -> Where {
|
||||
|
||||
return condition(self.meta)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//: ### Convenience Operators
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
public func .= <O: ManagedObjectProtocol, V: ImportableAttributeType>(_ attribute: AttributeContainer<O>.Required<V>, _ value: V) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
public func .= <O: ManagedObjectProtocol, V: ImportableAttributeType>(_ attribute: AttributeContainer<O>.Optional<V>, _ value: V?) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
postfix operator *
|
||||
public postfix func * <O: ManagedObjectProtocol, V: ImportableAttributeType>(_ attribute: AttributeContainer<O>.Required<V>) -> V {
|
||||
|
||||
return attribute.value
|
||||
}
|
||||
public postfix func * <O: ManagedObjectProtocol, V: ImportableAttributeType>(_ attribute: AttributeContainer<O>.Optional<V>) -> V? {
|
||||
|
||||
return attribute.value
|
||||
}
|
||||
|
||||
public extension AttributeContainer.Required where V: CVarArg {
|
||||
|
||||
public static func == (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
public static func < (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K < %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func > (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K > %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func <= (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K <= %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func >= (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value)
|
||||
}
|
||||
public static func != (_ attribute: AttributeContainer<O>.Required<V>, _ value: V) -> Where {
|
||||
|
||||
return Where("%K != %@", attribute.keyPath, value)
|
||||
}
|
||||
}
|
||||
public extension AttributeContainer.Optional where V: CVarArg {
|
||||
|
||||
public static func == (_ attribute: AttributeContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
}
|
||||
|
||||
public final class ModelVersion {
|
||||
|
||||
public let version: String
|
||||
internal let entities: Set<NSEntityDescription>
|
||||
internal let entityConfigurations: [String: Set<NSEntityDescription>]
|
||||
|
||||
public convenience init(version: String, entities: [EntityProtocol]) {
|
||||
|
||||
self.init(version: version, configurationEntities: [Into.defaultConfigurationName: entities])
|
||||
}
|
||||
|
||||
public required init(version: String, configurationEntities: [String: [EntityProtocol]]) {
|
||||
|
||||
self.version = version
|
||||
|
||||
var entityConfigurations: [String: Set<NSEntityDescription>] = [:]
|
||||
for (configuration, entities) in configurationEntities {
|
||||
|
||||
entityConfigurations[configuration] = Set(entities.map({ $0.entityDescription }))
|
||||
}
|
||||
let allEntities = Set(entityConfigurations.map({ $0.value }).joined())
|
||||
entityConfigurations[Into.defaultConfigurationName] = allEntities
|
||||
|
||||
self.entityConfigurations = entityConfigurations
|
||||
self.entities = allEntities
|
||||
}
|
||||
|
||||
internal func createModel() -> NSManagedObjectModel {
|
||||
|
||||
let model = NSManagedObjectModel()
|
||||
model.entities = self.entities.sorted(by: { $0.name! < $1.name! })
|
||||
for (configuration, entities) in self.entityConfigurations {
|
||||
|
||||
model.setEntities(
|
||||
entities.sorted(by: { $0.name! < $1.name! }),
|
||||
forConfigurationName: configuration
|
||||
)
|
||||
}
|
||||
return model
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public final class ICloudStore: CloudStorage {
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
|
||||
- parameter cloudStorageOptions: When the `ICloudStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
|
||||
*/
|
||||
public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: String? = nil, cloudStorageOptions: CloudStorageOptions = nil) {
|
||||
public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: ModelConfiguration = nil, cloudStorageOptions: CloudStorageOptions = nil) {
|
||||
|
||||
CoreStore.assert(
|
||||
!ubiquitousContentName.isEmpty,
|
||||
@@ -258,7 +258,7 @@ public final class ICloudStore: CloudStorage {
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
public let configuration: String?
|
||||
public let configuration: ModelConfiguration
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`. For `SQLiteStore`s, this is always set to
|
||||
|
||||
@@ -37,7 +37,7 @@ public final class InMemoryStore: StorageInterface, DefaultInitializableStore {
|
||||
Initializes an `InMemoryStore` for the specified configuration
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
|
||||
*/
|
||||
public init(configuration: String?) {
|
||||
public init(configuration: ModelConfiguration) {
|
||||
|
||||
self.configuration = configuration
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public final class InMemoryStore: StorageInterface, DefaultInitializableStore {
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
public let configuration: String?
|
||||
public let configuration: ModelConfiguration
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`. For `InMemoryStore`s, this is always set to `nil`.
|
||||
|
||||
@@ -44,7 +44,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
|
||||
- parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
|
||||
*/
|
||||
public init(fileURL: URL, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
public init(fileURL: URL, configuration: ModelConfiguration = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
|
||||
self.fileURL = fileURL
|
||||
self.configuration = configuration
|
||||
@@ -61,7 +61,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
|
||||
- parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
|
||||
*/
|
||||
public init(fileName: String, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
public init(fileName: String, configuration: ModelConfiguration = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
|
||||
self.fileURL = LegacySQLiteStore.defaultRootDirectory.appendingPathComponent(
|
||||
fileName,
|
||||
@@ -118,7 +118,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
public let configuration: String?
|
||||
public let configuration: ModelConfiguration
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`. For `SQLiteStore`s, this is always set to
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models (*.xcmappingmodel) for migration.
|
||||
- parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
|
||||
*/
|
||||
public init(fileURL: URL, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
public init(fileURL: URL, configuration: ModelConfiguration = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
|
||||
self.fileURL = fileURL
|
||||
self.configuration = configuration
|
||||
@@ -60,7 +60,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models (*.xcmappingmodel) for migration
|
||||
- parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
|
||||
*/
|
||||
public init(fileName: String, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
public init(fileName: String, configuration: ModelConfiguration = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
|
||||
|
||||
self.fileURL = SQLiteStore.defaultRootDirectory
|
||||
.appendingPathComponent(fileName, isDirectory: false)
|
||||
@@ -96,7 +96,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
public let configuration: String?
|
||||
public let configuration: ModelConfiguration
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`. For `SQLiteStore`s, this is always set to
|
||||
|
||||
@@ -41,7 +41,7 @@ public protocol StorageInterface: class {
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
var configuration: String? { get }
|
||||
var configuration: ModelConfiguration { get }
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`
|
||||
@@ -166,7 +166,7 @@ internal extension LocalStorage {
|
||||
internal func matchesPersistentStore(_ persistentStore: NSPersistentStore) -> Bool {
|
||||
|
||||
return persistentStore.type == type(of: self).storeType
|
||||
&& persistentStore.configurationName == (self.configuration ?? Into.defaultConfigurationName)
|
||||
&& persistentStore.configurationName == (self.configuration ?? DataStack.defaultConfigurationName)
|
||||
&& persistentStore.url == self.fileURL
|
||||
}
|
||||
}
|
||||
@@ -250,7 +250,7 @@ internal extension CloudStorage {
|
||||
internal func matchesPersistentStore(_ persistentStore: NSPersistentStore) -> Bool {
|
||||
|
||||
guard persistentStore.type == type(of: self).storeType
|
||||
&& persistentStore.configurationName == (self.configuration ?? Into.defaultConfigurationName) else {
|
||||
&& persistentStore.configurationName == (self.configuration ?? DataStack.defaultConfigurationName) else {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -83,12 +83,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
// MARK: BaseDataTransaction
|
||||
|
||||
/**
|
||||
Creates a new `NSManagedObject` with the specified entity type.
|
||||
Creates a new `NSManagedObject` or `ManagedObject` with the specified entity type.
|
||||
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `ManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` or `ManagedObject` instance of the specified entity type.
|
||||
*/
|
||||
public override func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
||||
public override func create<T: ManagedObjectProtocol>(_ into: Into<T>) -> T {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
|
||||
@@ -45,32 +45,36 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a new `NSManagedObject` with the specified entity type.
|
||||
Creates a new `NSManagedObject` or `ManagedObject` with the specified entity type.
|
||||
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `ManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` or `ManagedObject` instance of the specified entity type.
|
||||
*/
|
||||
public func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
||||
public func create<T: ManagedObjectProtocol>(_ into: Into<T>) -> T {
|
||||
|
||||
let entityClass = (into.entityClass as! T.Type)
|
||||
let entityClass = into.entityClass
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
|
||||
)
|
||||
|
||||
let context = self.context
|
||||
let dataStack = context.parentStack!
|
||||
let entityIdentifier = EntityIdentifier(entityClass)
|
||||
if into.inferStoreIfPossible {
|
||||
|
||||
switch context.parentStack!.persistentStoreForEntityClass(
|
||||
entityClass,
|
||||
switch dataStack.persistentStore(
|
||||
for: entityIdentifier,
|
||||
configuration: nil,
|
||||
inferStoreIfPossible: true
|
||||
) {
|
||||
|
||||
case (let persistentStore?, _):
|
||||
let object = entityClass.createInContext(context)
|
||||
context.assign(object, to: persistentStore)
|
||||
return object
|
||||
return entityClass.cs_forceCreate(
|
||||
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
|
||||
into: context,
|
||||
assignTo: persistentStore
|
||||
)
|
||||
|
||||
case (nil, true):
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||
@@ -81,17 +85,19 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
}
|
||||
else {
|
||||
|
||||
switch context.parentStack!.persistentStoreForEntityClass(
|
||||
entityClass,
|
||||
switch dataStack.persistentStore(
|
||||
for: entityIdentifier,
|
||||
configuration: into.configuration
|
||||
?? type(of: into).defaultConfigurationName,
|
||||
?? DataStack.defaultConfigurationName,
|
||||
inferStoreIfPossible: false
|
||||
) {
|
||||
|
||||
case (let persistentStore?, _):
|
||||
let object = entityClass.createInContext(context)
|
||||
context.assign(object, to: persistentStore)
|
||||
return object
|
||||
return entityClass.cs_forceCreate(
|
||||
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
|
||||
into: context,
|
||||
assignTo: persistentStore
|
||||
)
|
||||
|
||||
case (nil, true):
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||
@@ -143,7 +149,7 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
)
|
||||
CoreStore.assert(
|
||||
into.inferStoreIfPossible
|
||||
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
|
||||
|| (into.configuration ?? DataStack.defaultConfigurationName) == objectID.persistentStore?.configurationName,
|
||||
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
|
||||
)
|
||||
return self.fetchExisting(objectID) as? T
|
||||
@@ -160,11 +166,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete an entity outside its designated queue."
|
||||
)
|
||||
guard let object = object else {
|
||||
|
||||
return
|
||||
}
|
||||
self.context.fetchExisting(object)?.deleteFromContext()
|
||||
let context = self.context
|
||||
object
|
||||
.flatMap(context.fetchExisting)
|
||||
.flatMap(context.delete)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +197,7 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
)
|
||||
|
||||
let context = self.context
|
||||
objects.forEach { context.fetchExisting($0)?.deleteFromContext() }
|
||||
objects.forEach { context.fetchExisting($0).flatMap(context.delete) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,18 +39,18 @@ import CoreData
|
||||
let person = transaction.create(Into<MyPersonEntity>("Configuration1"))
|
||||
```
|
||||
*/
|
||||
public struct Into<T: NSManagedObject>: Hashable {
|
||||
public struct Into<T: ManagedObjectProtocol>: Hashable {
|
||||
|
||||
/**
|
||||
The associated `NSManagedObject` entity class
|
||||
The associated `NSManagedObject` or `ManagedObject` entity class
|
||||
*/
|
||||
public let entityClass: AnyClass
|
||||
public let entityClass: T.Type
|
||||
|
||||
/**
|
||||
The `NSPersistentStore` configuration name to associate objects from.
|
||||
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
|
||||
*/
|
||||
public let configuration: String?
|
||||
public let configuration: ModelConfiguration
|
||||
|
||||
/**
|
||||
Initializes an `Into` clause.
|
||||
@@ -58,7 +58,7 @@ public struct Into<T: NSManagedObject>: Hashable {
|
||||
let person = transaction.create(Into<MyPersonEntity>())
|
||||
```
|
||||
*/
|
||||
public init(){
|
||||
public init() {
|
||||
|
||||
self.init(entityClass: T.self, configuration: nil, inferStoreIfPossible: true)
|
||||
}
|
||||
@@ -75,22 +75,6 @@ public struct Into<T: NSManagedObject>: Hashable {
|
||||
self.init(entityClass: entity, configuration: nil, inferStoreIfPossible: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes an `Into` clause with the specified entity class.
|
||||
```
|
||||
let person = transaction.create(Into(MyPersonEntity.self))
|
||||
```
|
||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||
*/
|
||||
public init(_ entityClass: AnyClass) {
|
||||
|
||||
CoreStore.assert(
|
||||
entityClass is T.Type,
|
||||
"Attempted to create generic type \(cs_typeName(Into<T>.self)) with entity class \(cs_typeName(entityClass))"
|
||||
)
|
||||
self.init(entityClass: entityClass, configuration: nil, inferStoreIfPossible: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes an `Into` clause with the specified configuration.
|
||||
```
|
||||
@@ -98,7 +82,7 @@ public struct Into<T: NSManagedObject>: Hashable {
|
||||
```
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ configuration: String?) {
|
||||
public init(_ configuration: ModelConfiguration) {
|
||||
|
||||
self.init(entityClass: T.self, configuration: configuration, inferStoreIfPossible: false)
|
||||
}
|
||||
@@ -111,32 +95,15 @@ public struct Into<T: NSManagedObject>: Hashable {
|
||||
- parameter entity: the `NSManagedObject` type to be created
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ entity: T.Type, _ configuration: String?) {
|
||||
public init(_ entity: T.Type, _ configuration: ModelConfiguration) {
|
||||
|
||||
self.init(entityClass: entity, configuration: configuration, inferStoreIfPossible: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes an `Into` clause with the specified entity class and configuration.
|
||||
```
|
||||
let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
|
||||
```
|
||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ entityClass: AnyClass, _ configuration: String?) {
|
||||
|
||||
CoreStore.assert(
|
||||
entityClass is T.Type,
|
||||
"Attempted to create generic type \(cs_typeName(Into<T>.self)) with entity class \(cs_typeName(entityClass))"
|
||||
)
|
||||
self.init(entityClass: entityClass, configuration: configuration, inferStoreIfPossible: false)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == <T: NSManagedObject, U: NSManagedObject>(lhs: Into<T>, rhs: Into<U>) -> Bool {
|
||||
public static func == <U: ManagedObjectProtocol, V: ManagedObjectProtocol>(lhs: Into<U>, rhs: Into<V>) -> Bool {
|
||||
|
||||
return lhs.entityClass == rhs.entityClass
|
||||
&& lhs.configuration == rhs.configuration
|
||||
@@ -156,26 +123,9 @@ public struct Into<T: NSManagedObject>: Hashable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal static var defaultConfigurationName: String {
|
||||
|
||||
return "PF_DEFAULT_CONFIGURATION_NAME"
|
||||
}
|
||||
|
||||
internal let inferStoreIfPossible: Bool
|
||||
|
||||
internal func downcast() -> Into<NSManagedObject> {
|
||||
|
||||
return Into<NSManagedObject>(
|
||||
entityClass: self.entityClass,
|
||||
configuration: self.configuration,
|
||||
inferStoreIfPossible: self.inferStoreIfPossible
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(entityClass: AnyClass, configuration: String?, inferStoreIfPossible: Bool) {
|
||||
internal init(entityClass: T.Type, configuration: ModelConfiguration, inferStoreIfPossible: Bool) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configuration = configuration
|
||||
|
||||
@@ -43,22 +43,4 @@ public extension NSManagedObject {
|
||||
|
||||
return self.managedObjectContext?.parentTransaction as? UnsafeDataTransaction
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc
|
||||
internal class func createInContext(_ context: NSManagedObjectContext) -> Self {
|
||||
|
||||
return self.init(
|
||||
entity: context.entityDescriptionForEntityType(self)!,
|
||||
insertInto: context
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func deleteFromContext() {
|
||||
|
||||
self.managedObjectContext?.delete(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,12 +50,12 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
|
||||
// MARK: BaseDataTransaction
|
||||
|
||||
/**
|
||||
Creates a new `NSManagedObject` with the specified entity type.
|
||||
Creates a new `NSManagedObject` or `ManagedObject` with the specified entity type.
|
||||
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `ManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` or `ManagedObject` instance of the specified entity type.
|
||||
*/
|
||||
public override func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
||||
public override func create<T: ManagedObjectProtocol>(_ into: Into<T>) -> T {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
|
||||
Reference in New Issue
Block a user