mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-13 23:23:29 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2559375491 | ||
|
|
c923dfc12c | ||
|
|
a5936c1120 | ||
|
|
159448b36d | ||
|
|
7ee91834ab | ||
|
|
8faf44c166 | ||
|
|
7f4cfaf5a0 | ||
|
|
da4ac192db | ||
|
|
e9219682b5 | ||
|
|
6264022ccf |
@@ -11,12 +11,25 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.ios.deployment_target = "13.0"
|
||||
s.osx.deployment_target = "10.15"
|
||||
s.watchos.deployment_target = "6.0"
|
||||
s.tvos.deployment_target = "13.0"
|
||||
s.watchos.deployment_target = "7.4"
|
||||
|
||||
s.source_files = "Sources", "Sources/**/*.{swift,h,m}"
|
||||
s.source_files = "Sources", "Sources/**/*.swift"
|
||||
s.public_header_files = "Sources/**/*.h"
|
||||
s.frameworks = "Foundation", "CoreData"
|
||||
s.requires_arc = true
|
||||
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG', 'OTHER_LDFLAGS' => '-weak_framework Combine -weak_framework SwiftUI' }
|
||||
|
||||
s.test_spec "CoreStoreTests" do |ts|
|
||||
ts.source_files = "CoreStoreTests", "CoreStoreTests/**/*.swift", "CoreStoreTests/**/*.xcdatamodeld", "CoreStoreTests/**/*.xcdatamodel"
|
||||
ts.public_header_files = "CoreStoreTests/**/*.h"
|
||||
ts.resources = [ "CoreStoreTests/**/*.xcdatamodeld", "CoreStoreTests/**/*.xcdatamodel" ]
|
||||
ts.preserve_paths = "CoreStoreTests/**/*.xcdatamodeld"
|
||||
ts.frameworks = "Foundation", "CoreData"
|
||||
ts.requires_arc = true
|
||||
ts.ios.deployment_target = "13.0"
|
||||
ts.osx.deployment_target = "10.15"
|
||||
ts.tvos.deployment_target = "13.0"
|
||||
ts.watchos.deployment_target = "7.4"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,6 +180,35 @@
|
||||
B50EE14323473C96009B8C47 /* CoreStoreObject+DataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50EE14123473C92009B8C47 /* CoreStoreObject+DataSources.swift */; };
|
||||
B50EE14423473C97009B8C47 /* CoreStoreObject+DataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50EE14123473C92009B8C47 /* CoreStoreObject+DataSources.swift */; };
|
||||
B50EE14523473C97009B8C47 /* CoreStoreObject+DataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50EE14123473C92009B8C47 /* CoreStoreObject+DataSources.swift */; };
|
||||
B5114DA728CEEE5400EEAE78 /* SectionByTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557831D02A07400E51965 /* SectionByTests.swift */; };
|
||||
B5114DA828CEEE5400EEAE78 /* ConvenienceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */; };
|
||||
B5114DA928CEEE5400EEAE78 /* ListObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E0F1D0DA6AB009BC71E /* ListObserverTests.swift */; };
|
||||
B5114DAA28CEEE5400EEAE78 /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5519A3F1CA1B17B002BEF78 /* ErrorTests.swift */; };
|
||||
B5114DAB28CEEE5400EEAE78 /* GroupByTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525577B1D0291FE00E51965 /* GroupByTests.swift */; };
|
||||
B5114DAC28CEEE5400EEAE78 /* ListPublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D8CA7A2346EC550055D7D1 /* ListPublisherTests.swift */; };
|
||||
B5114DAD28CEEE5400EEAE78 /* WhereTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557731D02791400E51965 /* WhereTests.swift */; };
|
||||
B5114DAE28CEEE5400EEAE78 /* MigrationChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */; };
|
||||
B5114DAF28CEEE5400EEAE78 /* ImportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E0B1D0D0D19009BC71E /* ImportTests.swift */; };
|
||||
B5114DB028CEEE5400EEAE78 /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
|
||||
B5114DB128CEEE5400EEAE78 /* IntoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525576B1CFAF18F00E51965 /* IntoTests.swift */; };
|
||||
B5114DB228CEEE5400EEAE78 /* ObjectPublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B581B9312362BB8C002BDB2B /* ObjectPublisherTests.swift */; };
|
||||
B5114DB328CEEE5400EEAE78 /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
|
||||
B5114DB428CEEE5400EEAE78 /* FetchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557871D02DE8100E51965 /* FetchTests.swift */; };
|
||||
B5114DB528CEEE5400EEAE78 /* FromTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5489F4F1CF603D5008B4978 /* FromTests.swift */; };
|
||||
B5114DB628CEEE5400EEAE78 /* ObjectObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */; };
|
||||
B5114DB728CEEE5400EEAE78 /* OrderByTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557771D02826E00E51965 /* OrderByTests.swift */; };
|
||||
B5114DB828CEEE5400EEAE78 /* TestEntity2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5489F3E1CF5EEBC008B4978 /* TestEntity2.swift */; };
|
||||
B5114DB928CEEE5400EEAE78 /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525576F1D02561A00E51965 /* SelectTests.swift */; };
|
||||
B5114DBA28CEEE5400EEAE78 /* TransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5489F451CF5F017008B4978 /* TransactionTests.swift */; };
|
||||
B5114DBB28CEEE5400EEAE78 /* TweakTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525577F1D029D2500E51965 /* TweakTests.swift */; };
|
||||
B5114DBC28CEEE5400EEAE78 /* VersionLockTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59A51822256C85E00CEF3C5 /* VersionLockTests.swift */; };
|
||||
B5114DBD28CEEE5400EEAE78 /* BaseTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5489F4B1CF5F743008B4978 /* BaseTestCase.swift */; };
|
||||
B5114DBE28CEEE5400EEAE78 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
|
||||
B5114DBF28CEEE5400EEAE78 /* BaseTestDataTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */; };
|
||||
B5114DC028CEEE5400EEAE78 /* TestEntity1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5489F3D1CF5EEBC008B4978 /* TestEntity1.swift */; };
|
||||
B5114DC128CEEE5400EEAE78 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D27C11D0BC20100539C58 /* QueryTests.swift */; };
|
||||
B5114DC228CEEE5400EEAE78 /* StorageInterfaceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */; };
|
||||
B5114DC428CEEE5400EEAE78 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82BA18891C4BBCBA00A0916E /* CoreStore.framework */; };
|
||||
B512607F1E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; };
|
||||
B51260801E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; };
|
||||
B51260811E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */; };
|
||||
@@ -783,6 +812,14 @@
|
||||
B5F8496D234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; };
|
||||
B5F8496E234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; };
|
||||
B5F8496F234898240029D57B /* ListSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F8496B234898240029D57B /* ListSnapshot.swift */; };
|
||||
B5F9C093287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C092287849E0007AAD2E /* DataStack+Concurrency.swift */; };
|
||||
B5F9C094287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C092287849E0007AAD2E /* DataStack+Concurrency.swift */; };
|
||||
B5F9C095287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C092287849E0007AAD2E /* DataStack+Concurrency.swift */; };
|
||||
B5F9C096287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C092287849E0007AAD2E /* DataStack+Concurrency.swift */; };
|
||||
B5F9C098287850D6007AAD2E /* MigrationProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C097287850D6007AAD2E /* MigrationProgress.swift */; };
|
||||
B5F9C099287850D6007AAD2E /* MigrationProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C097287850D6007AAD2E /* MigrationProgress.swift */; };
|
||||
B5F9C09A287850D6007AAD2E /* MigrationProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C097287850D6007AAD2E /* MigrationProgress.swift */; };
|
||||
B5F9C09B287850D6007AAD2E /* MigrationProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F9C097287850D6007AAD2E /* MigrationProgress.swift */; };
|
||||
B5FAD6A91B50A4B400714891 /* Progress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */; };
|
||||
B5FAD6AC1B51285300714891 /* Internals.MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* Internals.MigrationManager.swift */; };
|
||||
B5FE4DA21C8481E100FA6A91 /* StorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FE4DA11C8481E100FA6A91 /* StorageInterface.swift */; };
|
||||
@@ -811,6 +848,13 @@
|
||||
remoteGlobalIDString = 82BA18881C4BBCBA00A0916E;
|
||||
remoteInfo = "CoreStore tvOS";
|
||||
};
|
||||
B5114DCB28CF0C2B00EEAE78 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 2F03A52719C5C6DA005002A5 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = B563216E1BD65082006C9394;
|
||||
remoteInfo = "CoreStore watchOS";
|
||||
};
|
||||
B52DD17F1BE1F8CD00949AFE /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 2F03A52719C5C6DA005002A5 /* Project object */;
|
||||
@@ -871,6 +915,7 @@
|
||||
B50E17602351FA66004F033C /* Internals.Closure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Internals.Closure.swift; sourceTree = "<group>"; };
|
||||
B50E42F623FBB91800ED476E /* ObjectProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectProxy.swift; sourceTree = "<group>"; };
|
||||
B50EE14123473C92009B8C47 /* CoreStoreObject+DataSources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoreStoreObject+DataSources.swift"; sourceTree = "<group>"; };
|
||||
B5114DC928CEEE5400EEAE78 /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStoreObject+Convenience.swift"; sourceTree = "<group>"; };
|
||||
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSEntityDescription+DynamicModel.swift"; sourceTree = "<group>"; };
|
||||
B51260921E9B28F100402229 /* Internals.EntityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Internals.EntityIdentifier.swift; sourceTree = "<group>"; };
|
||||
@@ -1061,6 +1106,8 @@
|
||||
B5F5848628633741001F57ED /* Module.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Module.swift; sourceTree = "<group>"; };
|
||||
B5F8496B234898240029D57B /* ListSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSnapshot.swift; sourceTree = "<group>"; };
|
||||
B5F849702348A6690029D57B /* EnvironmentValues+DataSources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+DataSources.swift"; sourceTree = "<group>"; };
|
||||
B5F9C092287849E0007AAD2E /* DataStack+Concurrency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataStack+Concurrency.swift"; sourceTree = "<group>"; };
|
||||
B5F9C097287850D6007AAD2E /* MigrationProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationProgress.swift; sourceTree = "<group>"; };
|
||||
B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Progress+Convenience.swift"; sourceTree = "<group>"; };
|
||||
B5FAD6AB1B51285300714891 /* Internals.MigrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Internals.MigrationManager.swift; sourceTree = "<group>"; };
|
||||
B5FE4DA11C8481E100FA6A91 /* StorageInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageInterface.swift; sourceTree = "<group>"; };
|
||||
@@ -1108,6 +1155,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B5114DC328CEEE5400EEAE78 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B5114DC428CEEE5400EEAE78 /* CoreStore.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B52DD1701BE1F8CC00949AFE /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1150,7 +1205,9 @@
|
||||
2F03A53C19C5C6DA005002A5 /* CoreStoreTests */,
|
||||
2F03A53119C5C6DA005002A5 /* Products */,
|
||||
);
|
||||
indentWidth = 4;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 4;
|
||||
};
|
||||
2F03A53119C5C6DA005002A5 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
@@ -1162,6 +1219,7 @@
|
||||
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */,
|
||||
82BA18891C4BBCBA00A0916E /* CoreStore.framework */,
|
||||
82BA18921C4BBCBA00A0916E /* CoreStoreTests.xctest */,
|
||||
B5114DC928CEEE5400EEAE78 /* CoreStoreTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -1430,6 +1488,7 @@
|
||||
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */,
|
||||
B549F6721E56A92800FBAB2D /* CoreDataNativeType.swift */,
|
||||
B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */,
|
||||
B5F9C091287849CB007AAD2E /* Swift Concurrency */,
|
||||
B5C795BE25D933C200BDACC1 /* Reactive Programming */,
|
||||
B52FEC722596DB6400368BFB /* SwiftUI */,
|
||||
B5E84EDA1AFF84500064E85B /* Setup */,
|
||||
@@ -1500,6 +1559,7 @@
|
||||
B5B866EC25F4800800335476 /* DataStack.AddStoragePublisher.swift */,
|
||||
B5944EFA25E8E8DA001D1D81 /* ListPublisher.SnapshotPublisher.swift */,
|
||||
B5B866DF25E9048000335476 /* ObjectPublisher.SnapshotPublisher.swift */,
|
||||
B5F9C097287850D6007AAD2E /* MigrationProgress.swift */,
|
||||
);
|
||||
name = "Reactive Programming";
|
||||
sourceTree = "<group>";
|
||||
@@ -1679,6 +1739,14 @@
|
||||
name = Internals;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5F9C091287849CB007AAD2E /* Swift Concurrency */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5F9C092287849E0007AAD2E /* DataStack+Concurrency.swift */,
|
||||
);
|
||||
name = "Swift Concurrency";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5FE4DA01C84818B00FA6A91 /* StorageInterfaces */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1799,6 +1867,24 @@
|
||||
productReference = 82BA18921C4BBCBA00A0916E /* CoreStoreTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
B5114DA328CEEE5400EEAE78 /* CoreStoreTests watchOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B5114DC628CEEE5400EEAE78 /* Build configuration list for PBXNativeTarget "CoreStoreTests watchOS" */;
|
||||
buildPhases = (
|
||||
B5114DA628CEEE5400EEAE78 /* Sources */,
|
||||
B5114DC328CEEE5400EEAE78 /* Frameworks */,
|
||||
B5114DC528CEEE5400EEAE78 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
B5114DCC28CF0C2B00EEAE78 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "CoreStoreTests watchOS";
|
||||
productName = "CoreStore tvOSTests";
|
||||
productReference = B5114DC928CEEE5400EEAE78 /* CoreStoreTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
B52DD1731BE1F8CC00949AFE /* CoreStore OSX */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B52DD18C1BE1F8CD00949AFE /* Build configuration list for PBXNativeTarget "CoreStore OSX" */;
|
||||
@@ -1910,6 +1996,7 @@
|
||||
82BA18881C4BBCBA00A0916E /* CoreStore tvOS */,
|
||||
82BA18911C4BBCBA00A0916E /* CoreStoreTests tvOS */,
|
||||
B563216E1BD65082006C9394 /* CoreStore watchOS */,
|
||||
B5114DA328CEEE5400EEAE78 /* CoreStoreTests watchOS */,
|
||||
B52DD1731BE1F8CC00949AFE /* CoreStore OSX */,
|
||||
B52DD17C1BE1F8CC00949AFE /* CoreStoreTests OSX */,
|
||||
);
|
||||
@@ -1945,6 +2032,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B5114DC528CEEE5400EEAE78 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B52DD1721BE1F8CC00949AFE /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2052,6 +2146,7 @@
|
||||
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */,
|
||||
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */,
|
||||
B5C7958F25D7D18000BDACC1 /* ListState.swift in Sources */,
|
||||
B5F9C098287850D6007AAD2E /* MigrationProgress.swift in Sources */,
|
||||
B5FE4DAC1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
|
||||
B5E41EC01EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
|
||||
B5A1DAC81F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
|
||||
@@ -2073,6 +2168,7 @@
|
||||
B50E175723517DE4004F033C /* Differentiable.swift in Sources */,
|
||||
B59AFF411C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift in Sources */,
|
||||
B5E84F231AFF84860064E85B /* ListMonitor.swift in Sources */,
|
||||
B5F9C093287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */,
|
||||
B5BF7FC6234D7E460070E741 /* ObjectSnapshot.swift in Sources */,
|
||||
B5E84EF71AFF846E0064E85B /* UnsafeDataTransaction.swift in Sources */,
|
||||
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */,
|
||||
@@ -2266,6 +2362,7 @@
|
||||
B56923C51EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
|
||||
82BA18C91C4BBD5900A0916E /* MigrationType.swift in Sources */,
|
||||
B5D8CA772346EAEE0055D7D1 /* DataStack+DataSources.swift in Sources */,
|
||||
B5F9C099287850D6007AAD2E /* MigrationProgress.swift in Sources */,
|
||||
82BA18D01C4BBD7100A0916E /* Internals.MigrationManager.swift in Sources */,
|
||||
B5DE5231230BDA1300A22534 /* CoreStoreDefaults.swift in Sources */,
|
||||
B56E4ED523CDB54A00E1708C /* FieldProtocol.swift in Sources */,
|
||||
@@ -2287,6 +2384,7 @@
|
||||
82BA18BF1C4BBD5300A0916E /* SectionBy.swift in Sources */,
|
||||
B5D339ED1E9495E500C880DE /* CoreStoreObject+Querying.swift in Sources */,
|
||||
B509D7D423C84E1900F42824 /* Transformable.Required.swift in Sources */,
|
||||
B5F9C094287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */,
|
||||
82BA18AC1C4BBD3100A0916E /* SynchronousDataTransaction.swift in Sources */,
|
||||
B50C3EE623D153EA00B29880 /* Field.Coded.swift in Sources */,
|
||||
82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */,
|
||||
@@ -2397,6 +2495,41 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B5114DA628CEEE5400EEAE78 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B5114DA728CEEE5400EEAE78 /* SectionByTests.swift in Sources */,
|
||||
B5114DA828CEEE5400EEAE78 /* ConvenienceTests.swift in Sources */,
|
||||
B5114DA928CEEE5400EEAE78 /* ListObserverTests.swift in Sources */,
|
||||
B5114DAA28CEEE5400EEAE78 /* ErrorTests.swift in Sources */,
|
||||
B5114DAB28CEEE5400EEAE78 /* GroupByTests.swift in Sources */,
|
||||
B5114DAC28CEEE5400EEAE78 /* ListPublisherTests.swift in Sources */,
|
||||
B5114DAD28CEEE5400EEAE78 /* WhereTests.swift in Sources */,
|
||||
B5114DAE28CEEE5400EEAE78 /* MigrationChainTests.swift in Sources */,
|
||||
B5114DAF28CEEE5400EEAE78 /* ImportTests.swift in Sources */,
|
||||
B5114DB028CEEE5400EEAE78 /* DynamicModelTests.swift in Sources */,
|
||||
B5114DB128CEEE5400EEAE78 /* IntoTests.swift in Sources */,
|
||||
B5114DB228CEEE5400EEAE78 /* ObjectPublisherTests.swift in Sources */,
|
||||
B5114DB328CEEE5400EEAE78 /* SetupTests.swift in Sources */,
|
||||
B5114DB428CEEE5400EEAE78 /* FetchTests.swift in Sources */,
|
||||
B5114DB528CEEE5400EEAE78 /* FromTests.swift in Sources */,
|
||||
B5114DB628CEEE5400EEAE78 /* ObjectObserverTests.swift in Sources */,
|
||||
B5114DB728CEEE5400EEAE78 /* OrderByTests.swift in Sources */,
|
||||
B5114DB828CEEE5400EEAE78 /* TestEntity2.swift in Sources */,
|
||||
B5114DB928CEEE5400EEAE78 /* SelectTests.swift in Sources */,
|
||||
B5114DBA28CEEE5400EEAE78 /* TransactionTests.swift in Sources */,
|
||||
B5114DBB28CEEE5400EEAE78 /* TweakTests.swift in Sources */,
|
||||
B5114DBC28CEEE5400EEAE78 /* VersionLockTests.swift in Sources */,
|
||||
B5114DBD28CEEE5400EEAE78 /* BaseTestCase.swift in Sources */,
|
||||
B5114DBE28CEEE5400EEAE78 /* Model.xcdatamodeld in Sources */,
|
||||
B5114DBF28CEEE5400EEAE78 /* BaseTestDataTestCase.swift in Sources */,
|
||||
B5114DC028CEEE5400EEAE78 /* TestEntity1.swift in Sources */,
|
||||
B5114DC128CEEE5400EEAE78 /* QueryTests.swift in Sources */,
|
||||
B5114DC228CEEE5400EEAE78 /* StorageInterfaceTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B52DD16F1BE1F8CC00949AFE /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2480,6 +2613,7 @@
|
||||
B5D8CA792346EAEF0055D7D1 /* DataStack+DataSources.swift in Sources */,
|
||||
B56E4ED723CDB54A00E1708C /* FieldProtocol.swift in Sources */,
|
||||
B56923C71EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
|
||||
B5F9C09B287850D6007AAD2E /* MigrationProgress.swift in Sources */,
|
||||
B5944EFE25E8E8DA001D1D81 /* ListPublisher.SnapshotPublisher.swift in Sources */,
|
||||
B5DE5233230BDA1300A22534 /* CoreStoreDefaults.swift in Sources */,
|
||||
B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */,
|
||||
@@ -2501,6 +2635,7 @@
|
||||
B52F74321E9B50D0005F3DAC /* SchemaHistory.swift in Sources */,
|
||||
B509D7D623C84E1900F42824 /* Transformable.Required.swift in Sources */,
|
||||
B50C3EE823D153EA00B29880 /* Field.Coded.swift in Sources */,
|
||||
B5F9C096287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */,
|
||||
B5D339EF1E9495E500C880DE /* CoreStoreObject+Querying.swift in Sources */,
|
||||
B52DD19F1BE1F92C00949AFE /* SynchronousDataTransaction.swift in Sources */,
|
||||
B52DD1CB1BE1F94600949AFE /* Internals.WeakObject.swift in Sources */,
|
||||
@@ -2694,6 +2829,7 @@
|
||||
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */,
|
||||
B5D8CA782346EAEF0055D7D1 /* DataStack+DataSources.swift in Sources */,
|
||||
B56923C61EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
|
||||
B5F9C09A287850D6007AAD2E /* MigrationProgress.swift in Sources */,
|
||||
B56321A71BD65216006C9394 /* MigrationResult.swift in Sources */,
|
||||
B56E4ED623CDB54A00E1708C /* FieldProtocol.swift in Sources */,
|
||||
B5DE5232230BDA1300A22534 /* CoreStoreDefaults.swift in Sources */,
|
||||
@@ -2715,6 +2851,7 @@
|
||||
B52F74311E9B50D0005F3DAC /* SchemaHistory.swift in Sources */,
|
||||
B563218F1BD65216006C9394 /* ImportableObject.swift in Sources */,
|
||||
B509D7D523C84E1900F42824 /* Transformable.Required.swift in Sources */,
|
||||
B5F9C095287849E0007AAD2E /* DataStack+Concurrency.swift in Sources */,
|
||||
B56321991BD65216006C9394 /* OrderBy.swift in Sources */,
|
||||
B50C3EE723D153EA00B29880 /* Field.Coded.swift in Sources */,
|
||||
B5D339EE1E9495E500C880DE /* CoreStoreObject+Querying.swift in Sources */,
|
||||
@@ -2798,6 +2935,11 @@
|
||||
target = 82BA18881C4BBCBA00A0916E /* CoreStore tvOS */;
|
||||
targetProxy = 82BA18941C4BBCBA00A0916E /* PBXContainerItemProxy */;
|
||||
};
|
||||
B5114DCC28CF0C2B00EEAE78 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = B563216E1BD65082006C9394 /* CoreStore watchOS */;
|
||||
targetProxy = B5114DCB28CF0C2B00EEAE78 /* PBXContainerItemProxy */;
|
||||
};
|
||||
B52DD1801BE1F8CD00949AFE /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = B52DD1731BE1F8CC00949AFE /* CoreStore OSX */;
|
||||
@@ -2879,7 +3021,7 @@
|
||||
TVOS_DEPLOYMENT_TARGET = 13.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 7.4;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -2944,7 +3086,7 @@
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 7.4;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -3117,6 +3259,46 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
B5114DC728CEEE5400EEAE78 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = CoreStoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = watchos;
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 7.4;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
B5114DC828CEEE5400EEAE78 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = CoreStoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = watchos;
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 7.4;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
B52DD1851BE1F8CD00949AFE /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -3190,7 +3372,7 @@
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = CoreStoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -3211,7 +3393,7 @@
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = CoreStoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
@@ -3242,7 +3424,7 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 7.4;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -3271,7 +3453,7 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 7.4;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -3323,6 +3505,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
B5114DC628CEEE5400EEAE78 /* Build configuration list for PBXNativeTarget "CoreStoreTests watchOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
B5114DC728CEEE5400EEAE78 /* Debug */,
|
||||
B5114DC828CEEE5400EEAE78 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
B52DD18C1BE1F8CD00949AFE /* Build configuration list for PBXNativeTarget "CoreStore OSX" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -20,6 +20,20 @@
|
||||
ReferencedContainer = "container:CoreStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "NO"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B5114DA328CEEE5400EEAE78"
|
||||
BuildableName = "CoreStoreTests.xctest"
|
||||
BlueprintName = "CoreStoreTests watchOS"
|
||||
ReferencedContainer = "container:CoreStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
@@ -28,6 +42,16 @@
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B5114DA328CEEE5400EEAE78"
|
||||
BuildableName = "CoreStoreTests.xctest"
|
||||
BlueprintName = "CoreStoreTests watchOS"
|
||||
ReferencedContainer = "container:CoreStore.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -28,6 +28,17 @@ import XCTest
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
#if !SWIFT_PACKAGE
|
||||
|
||||
extension Bundle {
|
||||
|
||||
static var module: Bundle {
|
||||
return Bundle(for: BaseTestCase.self)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - BaseTestCase
|
||||
|
||||
@@ -40,7 +51,7 @@ class BaseTestCase: XCTestCase {
|
||||
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
do {
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ final class ErrorTests: XCTestCase {
|
||||
let schemaHistory = SchemaHistory(
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
)
|
||||
let version = "1.0.0"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>6.2.1</string>
|
||||
<string>9.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -101,9 +101,9 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
let indexPath = userInfo?["indexPath"] as? IndexPath
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssertEqual(indexPath?.item, 0)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
@@ -213,14 +213,14 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
let indexPath = userInfo?["indexPath"] as? IndexPath
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
|
||||
switch object?.testEntityID {
|
||||
|
||||
case NSNumber(value: 101)?:
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
XCTAssertEqual(indexPath?.section, 1)
|
||||
XCTAssertEqual(indexPath?.item, 0)
|
||||
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
|
||||
@@ -230,8 +230,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
|
||||
|
||||
case NSNumber(value: 102)?:
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssertEqual(indexPath?.item, 0)
|
||||
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
|
||||
@@ -357,13 +357,13 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
["fromIndexPath", "toIndexPath", "object"]
|
||||
)
|
||||
|
||||
let fromIndexPath = userInfo?["fromIndexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(fromIndexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(fromIndexPath?.index(atPosition: 1), 0)
|
||||
let fromIndexPath = userInfo?["fromIndexPath"] as? IndexPath
|
||||
XCTAssertEqual(fromIndexPath?.section, 0)
|
||||
XCTAssertEqual(fromIndexPath?.item, 0)
|
||||
|
||||
let toIndexPath = userInfo?["toIndexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(toIndexPath?.index(atPosition: 0), 1)
|
||||
XCTAssertEqual(toIndexPath?.index(atPosition: 1), 1)
|
||||
let toIndexPath = userInfo?["toIndexPath"] as? IndexPath
|
||||
XCTAssertEqual(toIndexPath?.section, 1)
|
||||
XCTAssertEqual(toIndexPath?.item, 1)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
|
||||
@@ -465,10 +465,10 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
let indexPath = userInfo?["indexPath"] as? IndexPath
|
||||
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
|
||||
XCTAssert(indexPath?.item == 0 || indexPath?.item == 1)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.isDeleted, true)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14460.32" systemVersion="17G2307" minimumToolsVersion="Xcode 4.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||
<entity name="TestEntity1AAA" representedClassName="CoreStoreTests.TestEntity1" syncable="YES">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21279" systemVersion="21G83" minimumToolsVersion="Xcode 4.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||
<entity name="TestEntity1AAA" representedClassName=".TestEntity1" syncable="YES">
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||
@@ -12,7 +12,7 @@
|
||||
<relationship name="testToManyUnordered" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="TestEntity1AAA" inverseName="testToOne" inverseEntity="TestEntity1AAA" syncable="YES"/>
|
||||
<relationship name="testToOne" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TestEntity1AAA" inverseName="testToManyUnordered" inverseEntity="TestEntity1AAA" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="TestEntity2" representedClassName="CoreStoreTests.TestEntity2" syncable="YES">
|
||||
<entity name="TestEntity2" representedClassName=".TestEntity2" syncable="YES">
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||
@@ -30,8 +30,4 @@
|
||||
<configuration name="Config2">
|
||||
<memberEntity name="TestEntity2"/>
|
||||
</configuration>
|
||||
<elements>
|
||||
<element name="TestEntity1AAA" positionX="-63" positionY="-18" width="128" height="195"/>
|
||||
<element name="TestEntity2" positionX="-63" positionY="9" width="128" height="195"/>
|
||||
</elements>
|
||||
</model>
|
||||
@@ -42,7 +42,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
let schemaHistory = SchemaHistory(
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
)
|
||||
let stack = DataStack(schemaHistory: schemaHistory)
|
||||
@@ -68,7 +68,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self),
|
||||
bundle: Bundle.module,
|
||||
migrationChain: migrationChain
|
||||
)
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
do {
|
||||
|
||||
@@ -137,7 +137,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
do {
|
||||
|
||||
@@ -205,7 +205,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
try! stack.addStorageAndWait(sqliteStore)
|
||||
self.prepareTestDataForStack(stack)
|
||||
@@ -224,7 +224,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
let metadata = try createStore()
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
try sqliteStore.cs_eraseStorageAndWait(
|
||||
metadata: metadata,
|
||||
@@ -257,7 +257,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
do {
|
||||
|
||||
@@ -325,7 +325,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
try! stack.addStorageAndWait(
|
||||
SQLiteStore.legacy(
|
||||
@@ -351,7 +351,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
let metadata = try createStore()
|
||||
let stack = DataStack(
|
||||
xcodeModelName: "Model",
|
||||
bundle: Bundle(for: Self.self)
|
||||
bundle: Bundle.module
|
||||
)
|
||||
try sqliteStore.cs_eraseStorageAndWait(
|
||||
metadata: metadata,
|
||||
|
||||
@@ -103,7 +103,7 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
.appendingPathExtension("db")
|
||||
let mappingProvider = XcodeSchemaMappingProvider(
|
||||
from: "V1", to: "V2",
|
||||
mappingModelBundle: Bundle(for: Self.self)
|
||||
mappingModelBundle: Bundle.module
|
||||
)
|
||||
|
||||
let store = SQLiteStore(
|
||||
@@ -131,7 +131,7 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
let fileName = UUID().uuidString + ".db"
|
||||
let mappingProvider = XcodeSchemaMappingProvider(
|
||||
from: "V1", to: "V2",
|
||||
mappingModelBundle: Bundle(for: Self.self)
|
||||
mappingModelBundle: Bundle.module
|
||||
)
|
||||
let store = SQLiteStore(
|
||||
fileName: fileName,
|
||||
@@ -197,7 +197,7 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
let fileName = UUID().uuidString + ".db"
|
||||
let mappingProvider = XcodeSchemaMappingProvider(
|
||||
from: "V1", to: "V2",
|
||||
mappingModelBundle: Bundle(for: Self.self)
|
||||
mappingModelBundle: Bundle.module
|
||||
)
|
||||
let store = SQLiteStore.legacy(
|
||||
fileName: fileName,
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
@@ -426,9 +427,9 @@ final class TransactionTests: BaseTestCase {
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
let indexPath = userInfo?["indexPath"] as? IndexPath
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssertEqual(indexPath?.item, 0)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
|
||||
@@ -242,7 +242,9 @@
|
||||
B5A3911A24E5429200E7E8BD /* Products */,
|
||||
B5A3916624E698F900E7E8BD /* Frameworks */,
|
||||
);
|
||||
indentWidth = 4;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 4;
|
||||
};
|
||||
B5A3911A24E5429200E7E8BD /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// swift-tools-version:5.5
|
||||
// swift-tools-version:5.7
|
||||
//
|
||||
// Package.swift
|
||||
// CoreStore
|
||||
@@ -29,7 +29,7 @@ import PackageDescription
|
||||
let package = Package(
|
||||
name: "CoreStore",
|
||||
platforms: [
|
||||
.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6)
|
||||
.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v7)
|
||||
],
|
||||
products: [
|
||||
.library(name: "CoreStore", targets: ["CoreStore"])
|
||||
@@ -45,7 +45,10 @@ let package = Package(
|
||||
.testTarget(
|
||||
name: "CoreStoreTests",
|
||||
dependencies: ["CoreStore"],
|
||||
path: "CoreStoreTests"
|
||||
path: "CoreStoreTests",
|
||||
resources: [
|
||||
.process("Model.xcdatamodeld")
|
||||
]
|
||||
)
|
||||
],
|
||||
swiftLanguageVersions: [.v5]
|
||||
|
||||
16
README.md
16
README.md
@@ -20,8 +20,8 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
|
||||
<br />
|
||||
</p>
|
||||
|
||||
* **Swift 5.5:** iOS 11+ / macOS 10.13+ / watchOS 4.0+ / tvOS 11.0+
|
||||
* Previously supported Swift versions: [Swift 5.4](https://github.com/JohnEstropia/CoreStore/tree/8.0.1), [Swift 5.3](https://github.com/JohnEstropia/CoreStore/tree/7.3.1), [Swift 5.1](https://github.com/JohnEstropia/CoreStore/tree/7.0.4), [Swift 5.0](https://github.com/JohnEstropia/CoreStore/tree/6.3.2), [Swift 4.2](https://github.com/JohnEstropia/CoreStore/tree/6.2.1), [Swift 3.2](https://github.com/JohnEstropia/CoreStore/tree/4.2.3)
|
||||
* **Swift 5.7:** iOS 13+ / macOS 10.15+ / watchOS 7.4+ / tvOS 13.0+
|
||||
* Previously supported Swift versions: [Swift 5.5](https://github.com/JohnEstropia/CoreStore/tree/8.1.0), [Swift 5.4](https://github.com/JohnEstropia/CoreStore/tree/8.0.1), [Swift 5.3](https://github.com/JohnEstropia/CoreStore/tree/7.3.1)
|
||||
|
||||
Upgrading from previous CoreStore versions? Check out the [🆕 features](#features) and make sure to read the [Change logs](https://github.com/JohnEstropia/CoreStore/releases).
|
||||
|
||||
@@ -2438,9 +2438,9 @@ var body: some View {
|
||||
|
||||
# Installation
|
||||
- Requires:
|
||||
- iOS 10 SDK and above
|
||||
- Swift 5.2 (Xcode 11.4+)
|
||||
- For previous Swift versions: [Swift 3.2](https://github.com/JohnEstropia/CoreStore/tree/4.2.3), [Swift 4.2](https://github.com/JohnEstropia/CoreStore/tree/6.2.1), [Swift 5.0](https://github.com/JohnEstropia/CoreStore/tree/6.3.2), [Swift 5.1](https://github.com/JohnEstropia/CoreStore/tree/7.0.4)
|
||||
- iOS 13 SDK and above
|
||||
- Swift 5.7 (Xcode 14.0+)
|
||||
- For previous Swift versions: [Swift 5.5](https://github.com/JohnEstropia/CoreStore/tree/8.1.0), [Swift 5.4](https://github.com/JohnEstropia/CoreStore/tree/8.0.1), [Swift 5.3](https://github.com/JohnEstropia/CoreStore/tree/7.3.1)
|
||||
- Dependencies:
|
||||
- *None*
|
||||
- Other notes:
|
||||
@@ -2449,7 +2449,7 @@ var body: some View {
|
||||
### Install with CocoaPods
|
||||
In your `Podfile`, add
|
||||
```
|
||||
pod 'CoreStore', '~> 8.0'
|
||||
pod 'CoreStore', '~> 9.0'
|
||||
```
|
||||
and run
|
||||
```
|
||||
@@ -2460,7 +2460,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
|
||||
### Install with Carthage
|
||||
In your `Cartfile`, add
|
||||
```
|
||||
github "JohnEstropia/CoreStore" >= 8.0.0
|
||||
github "JohnEstropia/CoreStore" >= 9.0.0
|
||||
```
|
||||
and run
|
||||
```
|
||||
@@ -2471,7 +2471,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
|
||||
#### Install with Swift Package Manager:
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/JohnEstropia/CoreStore.git", from: "8.0.1"))
|
||||
.package(url: "https://github.com/JohnEstropia/CoreStore.git", from: "9.0.0"))
|
||||
]
|
||||
```
|
||||
Declare `import CoreStore` in your swift file to use the library.
|
||||
|
||||
@@ -78,6 +78,29 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
Attempted to perform a fetch but could not find any related persistent store.
|
||||
*/
|
||||
case persistentStoreNotFound(entity: DynamicObject.Type)
|
||||
|
||||
/**
|
||||
Casts any `Error` to a known `CoreStoreError`, or wraps it in `CoreStoreError.internalError(NSError:)`.
|
||||
*/
|
||||
public init(_ error: Error?) {
|
||||
|
||||
guard let error = error else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
switch error {
|
||||
|
||||
case let error as CoreStoreError:
|
||||
self = error
|
||||
|
||||
case let error as NSError:
|
||||
self = .internalError(NSError: error)
|
||||
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: CustomNSError
|
||||
@@ -253,29 +276,6 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(_ error: Error?) {
|
||||
|
||||
guard let error = error else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
switch error {
|
||||
|
||||
case let error as CoreStoreError:
|
||||
self = error
|
||||
|
||||
case let error as NSError:
|
||||
self = .internalError(NSError: error)
|
||||
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
367
Sources/DataStack+Concurrency.swift
Normal file
367
Sources/DataStack+Concurrency.swift
Normal file
@@ -0,0 +1,367 @@
|
||||
//
|
||||
// DataStack+Concurrency.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - DataStack
|
||||
|
||||
extension DataStack {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
Swift concurrency utilities for the `DataStack` are exposed through this namespace
|
||||
*/
|
||||
public var async: DataStack.AsyncNamespace {
|
||||
|
||||
return .init(self)
|
||||
}
|
||||
|
||||
// MARK: - ReactiveNamespace
|
||||
|
||||
/**
|
||||
Swift concurrency for the `DataStack` are exposed through this namespace. Extend this type if you need to add other `async` utilities for `DataStack`.
|
||||
*/
|
||||
public struct AsyncNamespace {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
The `DataStack` instance
|
||||
*/
|
||||
public let base: DataStack
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(_ base: DataStack) {
|
||||
|
||||
self.base = base
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - DataStack.AsyncNamespace
|
||||
|
||||
extension DataStack.AsyncNamespace {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `addStorage(...)` API. Asynchronously adds a `StorageInterface` to the stack.
|
||||
```
|
||||
let storage = try await dataStack.async.addStorage(
|
||||
InMemoryStore(configuration: "Config1")
|
||||
)
|
||||
```
|
||||
- parameter storage: the storage
|
||||
- returns: The `StorageInterface` instance added to the `DataStack`. Note that the `StorageInterface` event value may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func addStorage<T: StorageInterface>(
|
||||
_ storage: T
|
||||
) async throws -> T {
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.addStorage(
|
||||
storage,
|
||||
completion: continuation.resume(with:)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `addStorage(...)` API. Asynchronously adds a `LocalStorage` to the stack. Migrations are also initiated by default. The event emits `MigrationProgress` `enum` values.
|
||||
```
|
||||
for try await migrationProgress in dataStack.async.addStorage(
|
||||
SQLiteStore(
|
||||
fileName: "core_data.sqlite",
|
||||
configuration: "Config1"
|
||||
)
|
||||
) {
|
||||
|
||||
print("\(round(migrationProgress.fractionCompleted * 100)) %") // 0.0 ~ 1.0
|
||||
}
|
||||
```
|
||||
- parameter storage: the local storage
|
||||
- returns: An `AsyncThrowingStream` that emits a `MigrationProgress` value with metadata for migration progress. Note that the `LocalStorage` event value may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func addStorage<T>(
|
||||
_ storage: T
|
||||
) -> AsyncThrowingStream<MigrationProgress<T>, Swift.Error> {
|
||||
|
||||
return .init(
|
||||
bufferingPolicy: .unbounded,
|
||||
{ continuation in
|
||||
|
||||
var progress: Progress? = nil
|
||||
progress = self.base.addStorage(
|
||||
storage,
|
||||
completion: { result in
|
||||
|
||||
progress?.setProgressHandler(nil)
|
||||
|
||||
switch result {
|
||||
|
||||
case .success(let storage):
|
||||
continuation.yield(
|
||||
.finished(
|
||||
storage: storage,
|
||||
migrationRequired: progress != nil
|
||||
)
|
||||
)
|
||||
continuation.finish()
|
||||
|
||||
case .failure(let error):
|
||||
continuation.finish(
|
||||
throwing: error
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
if let progress = progress {
|
||||
|
||||
progress.setProgressHandler { progress in
|
||||
|
||||
continuation.yield(
|
||||
.migrating(
|
||||
storage: storage,
|
||||
progressObject: progress
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `importObject(...)` API. Creates an `ImportableObject` by importing from the specified import source. The event value will be the object instance correctly associated for the `DataStack`.
|
||||
```
|
||||
let object = try await dataStack.async.importObject(
|
||||
Into<Person>(),
|
||||
source: ["name": "John"]
|
||||
)
|
||||
```
|
||||
- parameter into: an `Into` clause specifying the entity type
|
||||
- parameter source: the object to import values from
|
||||
- returns: The object instance correctly associated for the `DataStack` if the object was imported successfully, or `nil` if the `ImportableObject` ignored the `source`.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func importObject<O: DynamicObject & ImportableObject>(
|
||||
_ into: Into<O>,
|
||||
source: O.ImportSource
|
||||
) async throws -> O? {
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.perform(
|
||||
asynchronous: { (transaction) -> O? in
|
||||
|
||||
return try transaction.importObject(
|
||||
into,
|
||||
source: source
|
||||
)
|
||||
},
|
||||
success: {
|
||||
|
||||
continuation.resume(
|
||||
with: .success($0.flatMap(self.base.fetchExisting))
|
||||
)
|
||||
},
|
||||
failure: continuation.resume(throwing:)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `importObject(...)` API. Updates an existing `ImportableObject` by importing values from the specified import source. The event value will be the object instance correctly associated for the `DataStack`.
|
||||
```
|
||||
let importedPerson = try await dataStack.async.importObject(
|
||||
existingPerson,
|
||||
source: ["name": "John", "age": 30]
|
||||
)
|
||||
```
|
||||
- parameter object: the object to update
|
||||
- parameter source: the object to import values from
|
||||
- returns: The object instance correctly associated for the `DataStack` if the object was imported successfully, or `nil` if the `ImportableObject` ignored the `source`.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func importObject<O: DynamicObject & ImportableObject>(
|
||||
_ object: O,
|
||||
source: O.ImportSource
|
||||
) async throws -> O? {
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.perform(
|
||||
asynchronous: { (transaction) -> O? in
|
||||
|
||||
guard let object = transaction.edit(object) else {
|
||||
|
||||
try transaction.cancel()
|
||||
}
|
||||
try transaction.importObject(
|
||||
object,
|
||||
source: source
|
||||
)
|
||||
return object
|
||||
},
|
||||
success: {
|
||||
|
||||
continuation.resume(
|
||||
with: .success($0.flatMap(self.base.fetchExisting))
|
||||
)
|
||||
},
|
||||
failure: continuation.resume(throwing:)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `importUniqueObject(...)` API. Updates an existing `ImportableUniqueObject` or creates a new instance by importing from the specified import source. The event value will be the object instance correctly associated for the `DataStack`.
|
||||
```
|
||||
let person = try await dataStack.async.importUniqueObject(
|
||||
Into<Person>(),
|
||||
source: ["name": "John", "age": 30]
|
||||
)
|
||||
```
|
||||
- parameter into: an `Into` clause specifying the entity type
|
||||
- parameter source: the object to import values from
|
||||
- returns: The object instance correctly associated for the `DataStack` if the object was imported successfully, or `nil` if the `ImportableUniqueObject` ignored the `source`.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func importUniqueObject<O: DynamicObject & ImportableUniqueObject>(
|
||||
_ into: Into<O>,
|
||||
source: O.ImportSource
|
||||
) async throws -> O? {
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.perform(
|
||||
asynchronous: { (transaction) -> O? in
|
||||
|
||||
return try transaction.importUniqueObject(
|
||||
into,
|
||||
source: source
|
||||
)
|
||||
},
|
||||
success: {
|
||||
|
||||
continuation.resume(
|
||||
with: .success($0.flatMap(self.base.fetchExisting))
|
||||
)
|
||||
},
|
||||
failure: continuation.resume(throwing:)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `importUniqueObjects(...)` API. Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources. `ImportableUniqueObject` methods are called on the objects in the same order as they are in the `sourceArray`, and are returned in an array with that same order. The event values will be object instances correctly associated for the `DataStack`.
|
||||
```
|
||||
let people = try await dataStack.async.importUniqueObjects(
|
||||
Into<Person>(),
|
||||
sourceArray: [
|
||||
["name": "John"],
|
||||
["name": "Bob"],
|
||||
["name": "Joe"]
|
||||
]
|
||||
)
|
||||
```
|
||||
- Warning: If `sourceArray` contains multiple import sources with same ID, no merging will occur and ONLY THE LAST duplicate will be imported.
|
||||
- parameter into: an `Into` clause specifying the entity type
|
||||
- parameter sourceArray: the array of objects to import values from
|
||||
- parameter preProcess: a closure that lets the caller tweak the internal `UniqueIDType`-to-`ImportSource` mapping to be used for importing. Callers can remove from/add to/update `mapping` and return the updated array from the closure.
|
||||
- returns: The imported objects correctly associated for the `DataStack`.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func importUniqueObjects<O: DynamicObject & ImportableUniqueObject, S: Sequence>(
|
||||
_ into: Into<O>,
|
||||
sourceArray: S,
|
||||
preProcess: @escaping (_ mapping: [O.UniqueIDType: O.ImportSource]) throws -> [O.UniqueIDType: O.ImportSource] = { $0 }
|
||||
) async throws -> [O]
|
||||
where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.perform(
|
||||
asynchronous: { (transaction) -> [O] in
|
||||
|
||||
return try transaction.importUniqueObjects(
|
||||
into,
|
||||
sourceArray: sourceArray,
|
||||
preProcess: preProcess
|
||||
)
|
||||
},
|
||||
success: {
|
||||
|
||||
continuation.resume(
|
||||
with: .success(self.base.fetchExisting($0))
|
||||
)
|
||||
},
|
||||
failure: continuation.resume(throwing:)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Swift concurrency extension for `CoreStore.DataStack`'s `perform(asynchronous:...)` API. Performs a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. The event value will be the value returned from the `task` closure. Any errors thrown from inside the `task` will be wrapped in a `CoreStoreError` before being thrown from the `async` method. To cancel/rollback changes, call `transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
|
||||
```
|
||||
let result = try await dataStack.async.perform(
|
||||
asynchronous: { (transaction) -> (inserted: Set<NSManagedObject>, deleted: Set<NSManagedObject>) in
|
||||
|
||||
// ...
|
||||
return (
|
||||
transaction.insertedObjects(),
|
||||
transaction.deletedObjects()
|
||||
)
|
||||
}
|
||||
)
|
||||
let inserted = dataStack.fetchExisting(result.inserted)
|
||||
let deleted = dataStack.fetchExisting(result.deleted)
|
||||
```
|
||||
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: The value returned from the `task` closure.
|
||||
- throws: A `CoreStoreError` value indicating the failure reason
|
||||
*/
|
||||
public func perform<Output>(
|
||||
_ asynchronous: @escaping (AsynchronousDataTransaction) throws -> Output
|
||||
) async throws -> Output {
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.perform(
|
||||
asynchronous: asynchronous,
|
||||
completion: continuation.resume(with:)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,9 @@ extension DataStack.ReactiveNamespace {
|
||||
- parameter storage: the storage
|
||||
- returns: A `Future` that emits a `StorageInterface` instance added to the `DataStack`. Note that the `StorageInterface` event value may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
public func addStorage<T: StorageInterface>(_ storage: T) -> Future<T, CoreStoreError> {
|
||||
public func addStorage<T: StorageInterface>(
|
||||
_ storage: T
|
||||
) -> Future<T, CoreStoreError> {
|
||||
|
||||
return .init { (promise) in
|
||||
|
||||
@@ -115,7 +117,7 @@ extension DataStack.ReactiveNamespace {
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive extension for `CoreStore.DataStack`'s `addStorage(...)` API. Asynchronously adds a `LocalStorage` to the stack. Migrations are also initiated by default. The event emits `DataStack.AddStoragePublisher.MigrationProgress` `enum` values.
|
||||
Reactive extension for `CoreStore.DataStack`'s `addStorage(...)` API. Asynchronously adds a `LocalStorage` to the stack. Migrations are also initiated by default. The event emits `MigrationProgress` `enum` values.
|
||||
```
|
||||
dataStack.reactive
|
||||
.addStorage(
|
||||
@@ -135,7 +137,7 @@ extension DataStack.ReactiveNamespace {
|
||||
.store(in: &cancellables)
|
||||
```
|
||||
- parameter storage: the local storage
|
||||
- returns: A `DataStack.AddStoragePublisher` that emits a `DataStack.AddStoragePublisher.MigrationProgress` value with metadata for migration progress. Note that the `LocalStorage` event value may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
||||
- returns: A `DataStack.AddStoragePublisher` that emits a `MigrationProgress` value with metadata for migration progress. Note that the `LocalStorage` event value may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
public func addStorage<T: LocalStorage>(_ storage: T) -> DataStack.AddStoragePublisher<T> {
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ extension DataStack {
|
||||
|
||||
// MARK: Publisher
|
||||
|
||||
public typealias Output = MigrationProgress
|
||||
public typealias Output = CoreStore.MigrationProgress<Storage>
|
||||
public typealias Failure = CoreStoreError
|
||||
|
||||
public func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
|
||||
@@ -63,56 +63,6 @@ extension DataStack {
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - MigrationProgress
|
||||
|
||||
/**
|
||||
A `MigrationProgress` contains info on a `LocalStorage`'s setup progress.
|
||||
|
||||
- SeeAlso: DataStack.reactive.addStorage(_:)
|
||||
*/
|
||||
public enum MigrationProgress {
|
||||
|
||||
/**
|
||||
The `LocalStorage` is currently being migrated
|
||||
*/
|
||||
case migrating(storage: Storage, progressObject: Progress)
|
||||
|
||||
/**
|
||||
The `LocalStorage` has been added to the `DataStack` and is ready for reading and writing
|
||||
*/
|
||||
case finished(storage: Storage, migrationRequired: Bool)
|
||||
|
||||
/**
|
||||
The fraction of the overall work completed by the migration. Returns a value between 0.0 and 1.0, inclusive.
|
||||
*/
|
||||
public var fractionCompleted: Double {
|
||||
|
||||
switch self {
|
||||
|
||||
case .migrating(_, let progressObject):
|
||||
return progressObject.fractionCompleted
|
||||
|
||||
case .finished:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns `true` if the storage was successfully added to the stack, `false` otherwise.
|
||||
*/
|
||||
public var isCompleted: Bool {
|
||||
|
||||
switch self {
|
||||
|
||||
case .migrating:
|
||||
return false
|
||||
|
||||
case .finished:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - AddStorageSubscriber
|
||||
|
||||
@@ -232,6 +182,12 @@ extension DataStack {
|
||||
private let storage: Storage
|
||||
private var subscriber: S?
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "MigrationProgress")
|
||||
public typealias MigrationProgress = CoreStore.MigrationProgress<Storage>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,11 @@ public final class DataStack: Equatable {
|
||||
- parameter bundle: an optional bundle to load .xcdatamodeld 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(xcodeModelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
|
||||
public convenience init(
|
||||
xcodeModelName: XcodeDataModelFileName = DataStack.applicationName,
|
||||
bundle: Bundle = Bundle.main,
|
||||
migrationChain: MigrationChain = nil
|
||||
) {
|
||||
|
||||
self.init(
|
||||
schemaHistory: SchemaHistory(
|
||||
@@ -79,7 +83,11 @@ public final class DataStack: Equatable {
|
||||
- parameter otherSchema: a list of other `DynamicSchema` instances that represent present/previous/future model versions, in any order
|
||||
- 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(_ schema: DynamicSchema, _ otherSchema: DynamicSchema..., migrationChain: MigrationChain = nil) {
|
||||
public convenience init(
|
||||
_ schema: DynamicSchema,
|
||||
_ otherSchema: DynamicSchema...,
|
||||
migrationChain: MigrationChain = nil
|
||||
) {
|
||||
|
||||
self.init(
|
||||
schemaHistory: SchemaHistory(
|
||||
@@ -108,7 +116,9 @@ public final class DataStack: Equatable {
|
||||
```
|
||||
- parameter schemaHistory: the `SchemaHistory` for the stack
|
||||
*/
|
||||
public required init(schemaHistory: SchemaHistory) {
|
||||
public required init(
|
||||
schemaHistory: SchemaHistory
|
||||
) {
|
||||
|
||||
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
|
||||
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
||||
@@ -139,7 +149,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
public func entityTypesByName(
|
||||
for type: NSManagedObject.Type
|
||||
) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
var entityTypesByName: [EntityName: NSManagedObject.Type] = [:]
|
||||
for (entityIdentifier, entityDescription) in self.schemaHistory.entityDescriptionsByEntityIdentifier {
|
||||
@@ -163,7 +175,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public func entityTypesByName(for type: CoreStoreObject.Type) -> [EntityName: CoreStoreObject.Type] {
|
||||
public func entityTypesByName(
|
||||
for type: CoreStoreObject.Type
|
||||
) -> [EntityName: CoreStoreObject.Type] {
|
||||
|
||||
var entityTypesByName: [EntityName: CoreStoreObject.Type] = [:]
|
||||
for (entityIdentifier, entityDescription) in self.schemaHistory.entityDescriptionsByEntityIdentifier {
|
||||
@@ -191,7 +205,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass.
|
||||
*/
|
||||
public func entityDescription(for type: NSManagedObject.Type) -> NSEntityDescription? {
|
||||
public func entityDescription(
|
||||
for type: NSManagedObject.Type
|
||||
) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescription(for: Internals.EntityIdentifier(type))
|
||||
}
|
||||
@@ -199,7 +215,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `CoreStoreObject` subclass.
|
||||
*/
|
||||
public func entityDescription(for type: CoreStoreObject.Type) -> NSEntityDescription? {
|
||||
public func entityDescription(
|
||||
for type: CoreStoreObject.Type
|
||||
) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescription(for: Internals.EntityIdentifier(type))
|
||||
}
|
||||
@@ -207,7 +225,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the `NSManagedObjectID` for the specified object URI if it exists in the persistent store.
|
||||
*/
|
||||
public func objectID(forURIRepresentation url: URL) -> NSManagedObjectID? {
|
||||
public func objectID(
|
||||
forURIRepresentation url: URL
|
||||
) -> NSManagedObjectID? {
|
||||
|
||||
return self.coordinator.managedObjectID(forURIRepresentation: url)
|
||||
}
|
||||
@@ -236,7 +256,9 @@ public final class DataStack: Equatable {
|
||||
- returns: the `StorageInterface` added to the stack
|
||||
*/
|
||||
@discardableResult
|
||||
public func addStorageAndWait<T: StorageInterface>(_ storage: T) throws -> T {
|
||||
public func addStorageAndWait<T: StorageInterface>(
|
||||
_ storage: T
|
||||
) throws -> T {
|
||||
|
||||
do {
|
||||
|
||||
@@ -275,7 +297,9 @@ public final class DataStack: Equatable {
|
||||
- returns: the local storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
@discardableResult
|
||||
public func addStorageAndWait<T: LocalStorage>(_ storage: T) throws -> T {
|
||||
public func addStorageAndWait<T: LocalStorage>(
|
||||
_ storage: T
|
||||
) throws -> T {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
|
||||
@@ -374,7 +398,9 @@ public final class DataStack: Equatable {
|
||||
Prepares deinitializing the `DataStack` by removing all persistent stores. This is not necessary, but can help silence SQLite warnings when actively releasing and recreating `DataStack`s.
|
||||
- parameter completion: the closure to execute after all persistent stores are removed
|
||||
*/
|
||||
public func unsafeRemoveAllPersistentStores(completion: @escaping () -> Void = {}) {
|
||||
public func unsafeRemoveAllPersistentStores(
|
||||
completion: @escaping () -> Void = {}
|
||||
) {
|
||||
|
||||
let coordinator = self.coordinator
|
||||
coordinator.performAsynchronously {
|
||||
@@ -441,7 +467,7 @@ public final class DataStack: Equatable {
|
||||
internal let mainContext: NSManagedObjectContext
|
||||
internal let schemaHistory: SchemaHistory
|
||||
internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue", qos: .utility)
|
||||
internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue", qos: .userInteractive)
|
||||
internal let storeMetadataLock: NSRecursiveLock = .init()
|
||||
internal let migrationQueue: OperationQueue = Internals.with {
|
||||
|
||||
let migrationQueue = OperationQueue()
|
||||
@@ -452,56 +478,68 @@ public final class DataStack: Equatable {
|
||||
return migrationQueue
|
||||
}
|
||||
|
||||
internal func persistentStoreForStorage(_ storage: StorageInterface) -> NSPersistentStore? {
|
||||
internal func persistentStoreForStorage(
|
||||
_ storage: StorageInterface
|
||||
) -> NSPersistentStore? {
|
||||
|
||||
return self.coordinator.persistentStores
|
||||
.filter { $0.storageInterface === storage }
|
||||
.first
|
||||
}
|
||||
|
||||
internal func persistentStores(for entityIdentifier: Internals.EntityIdentifier) -> [NSPersistentStore]? {
|
||||
|
||||
var returnValue: [NSPersistentStore]? = nil
|
||||
self.storeMetadataUpdateQueue.sync(flags: .barrier) {
|
||||
|
||||
returnValue = self.finalConfigurationsByEntityIdentifier[entityIdentifier]?
|
||||
.map({ self.persistentStoresByFinalConfiguration[$0]! }) ?? []
|
||||
internal func persistentStores(
|
||||
for entityIdentifier: Internals.EntityIdentifier
|
||||
) -> [NSPersistentStore]? {
|
||||
|
||||
self.storeMetadataLock.lock()
|
||||
defer {
|
||||
self.storeMetadataLock.unlock()
|
||||
}
|
||||
return returnValue
|
||||
return self.finalConfigurationsByEntityIdentifier[entityIdentifier]?
|
||||
.map({ self.persistentStoresByFinalConfiguration[$0]! }) ?? []
|
||||
}
|
||||
|
||||
internal func persistentStore(for entityIdentifier: Internals.EntityIdentifier, configuration: ModelConfiguration, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
|
||||
return self.storeMetadataUpdateQueue.sync(flags: .barrier) { () -> (store: NSPersistentStore?, isAmbiguous: Bool) in
|
||||
|
||||
let configurationsForEntity = self.finalConfigurationsByEntityIdentifier[entityIdentifier] ?? []
|
||||
if let configuration = configuration {
|
||||
|
||||
if configurationsForEntity.contains(configuration) {
|
||||
|
||||
return (store: self.persistentStoresByFinalConfiguration[configuration], isAmbiguous: false)
|
||||
}
|
||||
else if !inferStoreIfPossible {
|
||||
|
||||
return (store: nil, isAmbiguous: false)
|
||||
}
|
||||
internal func persistentStore(
|
||||
for entityIdentifier: Internals.EntityIdentifier,
|
||||
configuration: ModelConfiguration,
|
||||
inferStoreIfPossible: Bool
|
||||
) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
|
||||
self.storeMetadataLock.lock()
|
||||
defer {
|
||||
self.storeMetadataLock.unlock()
|
||||
}
|
||||
let configurationsForEntity = self.finalConfigurationsByEntityIdentifier[entityIdentifier] ?? []
|
||||
if let configuration = configuration {
|
||||
|
||||
if configurationsForEntity.contains(configuration) {
|
||||
|
||||
return (store: self.persistentStoresByFinalConfiguration[configuration], isAmbiguous: false)
|
||||
}
|
||||
|
||||
switch configurationsForEntity.count {
|
||||
|
||||
case 0:
|
||||
else if !inferStoreIfPossible {
|
||||
|
||||
return (store: nil, isAmbiguous: false)
|
||||
|
||||
case 1 where inferStoreIfPossible:
|
||||
return (store: self.persistentStoresByFinalConfiguration[configurationsForEntity.first!], isAmbiguous: false)
|
||||
|
||||
default:
|
||||
return (store: nil, isAmbiguous: true)
|
||||
}
|
||||
}
|
||||
|
||||
switch configurationsForEntity.count {
|
||||
|
||||
case 0:
|
||||
return (store: nil, isAmbiguous: false)
|
||||
|
||||
case 1 where inferStoreIfPossible:
|
||||
return (store: self.persistentStoresByFinalConfiguration[configurationsForEntity.first!], isAmbiguous: false)
|
||||
|
||||
default:
|
||||
return (store: nil, isAmbiguous: true)
|
||||
}
|
||||
}
|
||||
|
||||
internal func createPersistentStoreFromStorage(_ storage: StorageInterface, finalURL: URL?, finalStoreOptions: [AnyHashable: Any]?) throws -> NSPersistentStore {
|
||||
internal func createPersistentStoreFromStorage(
|
||||
_ storage: StorageInterface,
|
||||
finalURL: URL?,
|
||||
finalStoreOptions: [AnyHashable: Any]?
|
||||
) throws -> NSPersistentStore {
|
||||
|
||||
let persistentStore = try self.coordinator.addPersistentStore(
|
||||
ofType: type(of: storage).storeType,
|
||||
@@ -510,8 +548,13 @@ public final class DataStack: Equatable {
|
||||
options: finalStoreOptions
|
||||
)
|
||||
persistentStore.storageInterface = storage
|
||||
|
||||
self.storeMetadataUpdateQueue.async(flags: .barrier) {
|
||||
|
||||
do {
|
||||
|
||||
self.storeMetadataLock.lock()
|
||||
defer {
|
||||
self.storeMetadataLock.unlock()
|
||||
}
|
||||
|
||||
let configurationName = persistentStore.configurationName
|
||||
self.persistentStoresByFinalConfiguration[configurationName] = persistentStore
|
||||
@@ -534,7 +577,9 @@ public final class DataStack: Equatable {
|
||||
return persistentStore
|
||||
}
|
||||
|
||||
internal func entityDescription(for entityIdentifier: Internals.EntityIdentifier) -> NSEntityDescription? {
|
||||
internal func entityDescription(
|
||||
for entityIdentifier: Internals.EntityIdentifier
|
||||
) -> NSEntityDescription? {
|
||||
|
||||
return self.schemaHistory.entityDescriptionsByEntityIdentifier[entityIdentifier]
|
||||
}
|
||||
|
||||
79
Sources/MigrationProgress.swift
Normal file
79
Sources/MigrationProgress.swift
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// MigrationProgress.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2021 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - MigrationProgress
|
||||
|
||||
/**
|
||||
A `MigrationProgress` contains info on a `LocalStorage`'s setup progress.
|
||||
|
||||
- SeeAlso: DataStack.reactive.addStorage(_:)
|
||||
- SeeAlso: DataStack.async.addStorage(_:)
|
||||
*/
|
||||
public enum MigrationProgress<T: LocalStorage> {
|
||||
|
||||
/**
|
||||
The `LocalStorage` is currently being migrated
|
||||
*/
|
||||
case migrating(storage: T, progressObject: Progress)
|
||||
|
||||
/**
|
||||
The `LocalStorage` has been added to the `DataStack` and is ready for reading and writing
|
||||
*/
|
||||
case finished(storage: T, migrationRequired: Bool)
|
||||
|
||||
/**
|
||||
The fraction of the overall work completed by the migration. Returns a value between 0.0 and 1.0, inclusive.
|
||||
*/
|
||||
public var fractionCompleted: Double {
|
||||
|
||||
switch self {
|
||||
|
||||
case .migrating(_, let progressObject):
|
||||
return progressObject.fractionCompleted
|
||||
|
||||
case .finished:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns `true` if the storage was successfully added to the stack, `false` otherwise.
|
||||
*/
|
||||
public var isCompleted: Bool {
|
||||
|
||||
switch self {
|
||||
|
||||
case .migrating:
|
||||
return false
|
||||
|
||||
case .finished:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,7 +197,8 @@ public struct Where<O: DynamicObject>: WhereClauseType, FetchClause, QueryClause
|
||||
)
|
||||
}
|
||||
switch value {
|
||||
|
||||
|
||||
#if swift(>=5.7)
|
||||
case let optionalValue as any FieldOptionalType:
|
||||
switch optionalValue.cs_wrappedValue {
|
||||
|
||||
@@ -209,6 +210,12 @@ public struct Where<O: DynamicObject>: WhereClauseType, FetchClause, QueryClause
|
||||
self.init(valuePredicate)
|
||||
}
|
||||
|
||||
#else
|
||||
case nil:
|
||||
self.init(nilPredicate)
|
||||
|
||||
#endif
|
||||
|
||||
case is NSNull:
|
||||
self.init(nilPredicate)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user