mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-05 07:40:09 +01:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
104def4611 | ||
|
|
5dcf29011a | ||
|
|
c9e091a6a4 | ||
|
|
010a79ef6a | ||
|
|
9f9ecb4820 | ||
|
|
3fb2b5927b | ||
|
|
7c2129e38f | ||
|
|
4b6d9a54e7 | ||
|
|
cbf101506c | ||
|
|
9045fbbf1b | ||
|
|
0ee4dc89aa | ||
|
|
30d5e0a64a | ||
|
|
320c6145f8 | ||
|
|
7e37219315 | ||
|
|
d8235cf2e5 | ||
|
|
5cc34ff2e4 | ||
|
|
d4d76c87c9 | ||
|
|
073a1bdee3 | ||
|
|
118bb685fc | ||
|
|
5d0c4bf8ac | ||
|
|
a8bd937c68 | ||
|
|
7988d98b92 | ||
|
|
4b4ae61635 | ||
|
|
535b33ca75 | ||
|
|
b88ade92d6 | ||
|
|
a682f90aff | ||
|
|
f7c3e42009 | ||
|
|
2559375491 | ||
|
|
c923dfc12c | ||
|
|
a5936c1120 | ||
|
|
159448b36d | ||
|
|
7ee91834ab | ||
|
|
8faf44c166 | ||
|
|
7f4cfaf5a0 | ||
|
|
da4ac192db | ||
|
|
e9219682b5 | ||
|
|
6264022ccf |
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CoreStore"
|
||||
s.version = "9.0.0"
|
||||
s.swift_version = "5.7"
|
||||
s.version = "9.3.0"
|
||||
s.swift_version = "5.9"
|
||||
s.license = "MIT"
|
||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||
s.documentation_url = "https://JohnEstropia.github.io/CoreStore"
|
||||
@@ -9,14 +9,27 @@ Pod::Spec.new do |s|
|
||||
s.author = { "John Rommel Estropia" => "rommel.estropia@gmail.com" }
|
||||
s.source = { :git => "https://github.com/JohnEstropia/CoreStore.git", :tag => s.version.to_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.ios.deployment_target = "16.0"
|
||||
s.osx.deployment_target = "13.0"
|
||||
s.tvos.deployment_target = "16.0"
|
||||
s.watchos.deployment_target = "9.0"
|
||||
|
||||
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.resource_bundles = { 'CoreStoreTests' => ["CoreStoreTests/**/*.momd"] }
|
||||
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"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -15,6 +15,10 @@
|
||||
18166889232B9ED80097C275 /* String+KeyPaths.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51B5C2A22D43931009FA3BA /* String+KeyPaths.swift */; };
|
||||
2F03A53619C5C6DA005002A5 /* CoreStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F03A53519C5C6DA005002A5 /* CoreStore.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A54C19C5C872005002A5 /* CoreData.framework */; };
|
||||
53EB03E62A3AD5D400179430 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53EB03E52A3AD5D400179430 /* Operators.swift */; };
|
||||
53EB03E72A3AD5D400179430 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53EB03E52A3AD5D400179430 /* Operators.swift */; };
|
||||
53EB03E82A3AD5D400179430 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53EB03E52A3AD5D400179430 /* Operators.swift */; };
|
||||
53EB03E92A3AD5D400179430 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53EB03E52A3AD5D400179430 /* Operators.swift */; };
|
||||
82BA18931C4BBCBA00A0916E /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82BA18891C4BBCBA00A0916E /* CoreStore.framework */; };
|
||||
82BA18A01C4BBD1400A0916E /* CoreStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F03A53519C5C6DA005002A5 /* CoreStore.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
82BA18A21C4BBD1D00A0916E /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; };
|
||||
@@ -180,6 +184,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 +816,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 +852,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 */;
|
||||
@@ -834,6 +882,7 @@
|
||||
2F03A53B19C5C6DA005002A5 /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2F03A53E19C5C6DA005002A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
2F03A54C19C5C872005002A5 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
53EB03E52A3AD5D400179430 /* Operators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
|
||||
82BA18891C4BBCBA00A0916E /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
82BA18921C4BBCBA00A0916E /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
82BA18DE1C4BBE2600A0916E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
|
||||
@@ -871,6 +920,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 +1111,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 +1160,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 +1210,9 @@
|
||||
2F03A53C19C5C6DA005002A5 /* CoreStoreTests */,
|
||||
2F03A53119C5C6DA005002A5 /* Products */,
|
||||
);
|
||||
indentWidth = 4;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 4;
|
||||
};
|
||||
2F03A53119C5C6DA005002A5 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
@@ -1162,6 +1224,7 @@
|
||||
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */,
|
||||
82BA18891C4BBCBA00A0916E /* CoreStore.framework */,
|
||||
82BA18921C4BBCBA00A0916E /* CoreStoreTests.xctest */,
|
||||
B5114DC928CEEE5400EEAE78 /* CoreStoreTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -1393,6 +1456,7 @@
|
||||
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */,
|
||||
B5D339E61E9493A500C880DE /* Entity.swift */,
|
||||
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */,
|
||||
53EB03E52A3AD5D400179430 /* Operators.swift */,
|
||||
);
|
||||
name = "Dynamic Models";
|
||||
sourceTree = "<group>";
|
||||
@@ -1430,6 +1494,7 @@
|
||||
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */,
|
||||
B549F6721E56A92800FBAB2D /* CoreDataNativeType.swift */,
|
||||
B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */,
|
||||
B5F9C091287849CB007AAD2E /* Swift Concurrency */,
|
||||
B5C795BE25D933C200BDACC1 /* Reactive Programming */,
|
||||
B52FEC722596DB6400368BFB /* SwiftUI */,
|
||||
B5E84EDA1AFF84500064E85B /* Setup */,
|
||||
@@ -1500,6 +1565,7 @@
|
||||
B5B866EC25F4800800335476 /* DataStack.AddStoragePublisher.swift */,
|
||||
B5944EFA25E8E8DA001D1D81 /* ListPublisher.SnapshotPublisher.swift */,
|
||||
B5B866DF25E9048000335476 /* ObjectPublisher.SnapshotPublisher.swift */,
|
||||
B5F9C097287850D6007AAD2E /* MigrationProgress.swift */,
|
||||
);
|
||||
name = "Reactive Programming";
|
||||
sourceTree = "<group>";
|
||||
@@ -1679,6 +1745,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 +1873,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" */;
|
||||
@@ -1859,8 +1951,9 @@
|
||||
2F03A52719C5C6DA005002A5 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 1400;
|
||||
LastUpgradeCheck = 1600;
|
||||
ORGANIZATIONNAME = "John Rommel Estropia";
|
||||
TargetAttributes = {
|
||||
2F03A52F19C5C6DA005002A5 = {
|
||||
@@ -1910,6 +2003,7 @@
|
||||
82BA18881C4BBCBA00A0916E /* CoreStore tvOS */,
|
||||
82BA18911C4BBCBA00A0916E /* CoreStoreTests tvOS */,
|
||||
B563216E1BD65082006C9394 /* CoreStore watchOS */,
|
||||
B5114DA328CEEE5400EEAE78 /* CoreStoreTests watchOS */,
|
||||
B52DD1731BE1F8CC00949AFE /* CoreStore OSX */,
|
||||
B52DD17C1BE1F8CC00949AFE /* CoreStoreTests OSX */,
|
||||
);
|
||||
@@ -1945,6 +2039,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B5114DC528CEEE5400EEAE78 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B52DD1721BE1F8CC00949AFE /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2052,6 +2153,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,8 +2175,10 @@
|
||||
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 */,
|
||||
53EB03E62A3AD5D400179430 /* Operators.swift in Sources */,
|
||||
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */,
|
||||
B5D339DD1E9489C700C880DE /* DynamicObject.swift in Sources */,
|
||||
B50C3EE523D153EA00B29880 /* Field.Coded.swift in Sources */,
|
||||
@@ -2266,6 +2370,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,8 +2392,10 @@
|
||||
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 */,
|
||||
53EB03E72A3AD5D400179430 /* Operators.swift in Sources */,
|
||||
82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */,
|
||||
B5215CAA1FA4810300139E3A /* QueryChainBuilder.swift in Sources */,
|
||||
B50E175823517DE4004F033C /* Differentiable.swift in Sources */,
|
||||
@@ -2397,6 +2504,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 +2622,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,8 +2644,10 @@
|
||||
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 */,
|
||||
53EB03E92A3AD5D400179430 /* Operators.swift in Sources */,
|
||||
B52DD1CB1BE1F94600949AFE /* Internals.WeakObject.swift in Sources */,
|
||||
B5220E1A1D130791009BC71E /* Internals.CoreStoreFetchedResultsController.swift in Sources */,
|
||||
B5215CAC1FA4810300139E3A /* QueryChainBuilder.swift in Sources */,
|
||||
@@ -2694,6 +2839,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,8 +2861,10 @@
|
||||
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 */,
|
||||
53EB03E82A3AD5D400179430 /* Operators.swift in Sources */,
|
||||
B5D339EE1E9495E500C880DE /* CoreStoreObject+Querying.swift in Sources */,
|
||||
B56321A51BD65216006C9394 /* MigrationChain.swift in Sources */,
|
||||
B56321A21BD65216006C9394 /* ListObserver.swift in Sources */,
|
||||
@@ -2798,6 +2946,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 */;
|
||||
@@ -2863,8 +3016,8 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Sources/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.5;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_SWIFT_FLAGS = "-D DEBUG";
|
||||
@@ -2876,10 +3029,10 @@
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TVOS_DEPLOYMENT_TARGET = 13.0;
|
||||
TVOS_DEPLOYMENT_TARGET = 16.6;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 9.6;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -2930,21 +3083,22 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Sources/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
|
||||
PRODUCT_NAME = CoreStore;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TVOS_DEPLOYMENT_TARGET = 13.0;
|
||||
TVOS_DEPLOYMENT_TARGET = 16.6;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 9.6;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -2958,9 +3112,12 @@
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -2982,9 +3139,12 @@
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3006,7 +3166,11 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = CoreStoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -3021,7 +3185,11 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
INFOPLIST_FILE = CoreStoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -3041,8 +3209,12 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3052,7 +3224,6 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 13.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -3068,8 +3239,12 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3079,7 +3254,6 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 13.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -3090,7 +3264,11 @@
|
||||
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";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = appletvos;
|
||||
@@ -3108,7 +3286,11 @@
|
||||
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";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = appletvos;
|
||||
@@ -3117,6 +3299,52 @@
|
||||
};
|
||||
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;
|
||||
};
|
||||
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;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
B52DD1851BE1F8CD00949AFE /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -3133,9 +3361,13 @@
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.5;
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3164,9 +3396,13 @@
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.5;
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3189,8 +3425,12 @@
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
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;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -3210,8 +3450,12 @@
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
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;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = CoreStoreTests;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
@@ -3231,8 +3475,12 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3242,7 +3490,6 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -3260,8 +3507,12 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MARKETING_VERSION = 9.0.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 9.3.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
Combine,
|
||||
@@ -3271,7 +3522,6 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 6.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -3323,6 +3573,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 = (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -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.3.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="22222" systemVersion="22G91" 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))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -242,7 +242,9 @@
|
||||
B5A3911A24E5429200E7E8BD /* Products */,
|
||||
B5A3916624E698F900E7E8BD /* Frameworks */,
|
||||
);
|
||||
indentWidth = 4;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 4;
|
||||
};
|
||||
B5A3911A24E5429200E7E8BD /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
@@ -620,8 +622,9 @@
|
||||
B5A3910F24E5424E00E7E8BD /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 1160;
|
||||
LastUpgradeCheck = 1400;
|
||||
LastUpgradeCheck = 1600;
|
||||
TargetAttributes = {
|
||||
B5A3911824E5429200E7E8BD = {
|
||||
CreatedOnToolsVersion = 11.6;
|
||||
@@ -790,6 +793,7 @@
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
@@ -797,7 +801,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -825,6 +829,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
@@ -832,7 +837,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -892,7 +897,6 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -960,7 +964,6 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -40,7 +40,7 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
.padding(),
|
||||
alignment: .leading
|
||||
)
|
||||
.animation(.default)
|
||||
.animation(.default, value: palette)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ extension Modern.ColorsDemo.SwiftUI {
|
||||
}
|
||||
}
|
||||
}
|
||||
.animation(.default)
|
||||
// .animation(.default) // breaks layout
|
||||
.listStyle(PlainListStyle())
|
||||
.edgesIgnoringSafeArea([])
|
||||
}
|
||||
|
||||
@@ -77,13 +77,12 @@ extension Modern.PlacemarksDemo {
|
||||
) -> MKAnnotationView? {
|
||||
|
||||
let identifier = "MKAnnotationView"
|
||||
var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
|
||||
var annotationView: MKMarkerAnnotationView! = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView
|
||||
if annotationView == nil {
|
||||
|
||||
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
|
||||
annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
|
||||
annotationView.isEnabled = true
|
||||
annotationView.canShowCallout = true
|
||||
annotationView.animatesDrop = true
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// swift-tools-version:5.5
|
||||
// swift-tools-version:5.9
|
||||
//
|
||||
// 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(.v13), .iOS(.v16), .tvOS(.v16), .watchOS(.v9)
|
||||
],
|
||||
products: [
|
||||
.library(name: "CoreStore", targets: ["CoreStore"])
|
||||
@@ -39,13 +39,15 @@ let package = Package(
|
||||
.target(
|
||||
name: "CoreStore",
|
||||
dependencies: [],
|
||||
path: "Sources",
|
||||
exclude: ["CoreStoreBridge.h", "CoreStoreBridge.m"]
|
||||
path: "Sources"
|
||||
),
|
||||
.testTarget(
|
||||
name: "CoreStoreTests",
|
||||
dependencies: ["CoreStore"],
|
||||
path: "CoreStoreTests"
|
||||
path: "CoreStoreTests",
|
||||
resources: [
|
||||
.process("Model.xcdatamodeld")
|
||||
]
|
||||
)
|
||||
],
|
||||
swiftLanguageVersions: [.v5]
|
||||
|
||||
@@ -17,6 +17,12 @@ class Animal: CoreStoreObject {
|
||||
var master: Person?
|
||||
}
|
||||
|
||||
class Dog: Animal {
|
||||
|
||||
@Field.Stored("name")
|
||||
var name: String = ""
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Stored("name")
|
||||
@@ -33,16 +39,20 @@ let dataStack = DataStack(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Person>("Person")
|
||||
],
|
||||
Entity<Person>("Person"),
|
||||
Entity<Dog>("Dog")
|
||||
]/*,
|
||||
versionLock: [
|
||||
"Animal": [0x4a201cc685d53c0a, 0x16e6c3b561577875, 0xb032e2da61c792a0, 0xa133b801051acee4],
|
||||
"Person": [0xca938eea1af4bd56, 0xbca30994506356ad, 0x7a7cc655898816ef, 0x1a4551ffedc9b214]
|
||||
]
|
||||
]*/
|
||||
)
|
||||
)
|
||||
dataStack.addStorage(
|
||||
SQLiteStore(fileName: "data.sqlite"),
|
||||
SQLiteStore(
|
||||
fileName: "data.sqlite",
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
),
|
||||
completion: { result in
|
||||
|
||||
switch result {
|
||||
@@ -73,8 +83,8 @@ dataStack.addStorage(
|
||||
case .success:
|
||||
/// Accessing Objects =====
|
||||
let bird = try! dataStack.fetchOne(
|
||||
From<Animal>()
|
||||
.where(\.$species == "Sparrow")
|
||||
From<Dog>()
|
||||
.where(\Dog.$species == "Sparrow")
|
||||
)!
|
||||
print(bird.species)
|
||||
print(bird.color as Any)
|
||||
|
||||
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.9:** iOS 16.0+ / macOS 13.0+ / watchOS 9.0+ / tvOS 16.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.7](https://github.com/JohnEstropia/CoreStore/tree/9.1.0)
|
||||
|
||||
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.1'
|
||||
```
|
||||
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.3.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.3.0"))
|
||||
]
|
||||
```
|
||||
Declare `import CoreStore` in your swift file to use the library.
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
```
|
||||
- Important: Never use `try?` or `try!` on a `cancel()` call. Always use `try`. Using `try?` will swallow the cancellation and the transaction will proceed to commit as normal. Using `try!` will crash the app as `cancel()` will *always* throw an error.
|
||||
*/
|
||||
public func cancel() throws -> Never {
|
||||
public func cancel() throws(CoreStoreError) -> Never {
|
||||
|
||||
throw CoreStoreError.userCancelled
|
||||
}
|
||||
@@ -66,8 +66,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
|
||||
*/
|
||||
public override func create<O>(_ into: Into<O>) -> O {
|
||||
|
||||
public override func create<O>(
|
||||
_ into: Into<O>
|
||||
) -> O {
|
||||
|
||||
Internals.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to create an entity of type \(Internals.typeName(into.entityClass)) from an already committed \(Internals.typeName(self))."
|
||||
@@ -82,8 +84,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||
*/
|
||||
public override func edit<O: DynamicObject>(_ object: O?) -> O? {
|
||||
|
||||
public override func edit<O: DynamicObject>(
|
||||
_ object: O?
|
||||
) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to update an entity of type \(Internals.typeName(object)) from an already committed \(Internals.typeName(self))."
|
||||
@@ -99,8 +103,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||
*/
|
||||
public override func edit<O>(_ into: Into<O>, _ objectID: NSManagedObjectID) -> O? {
|
||||
|
||||
public override func edit<O>(
|
||||
_ into: Into<O>,
|
||||
_ objectID: NSManagedObjectID
|
||||
) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to update an entity of type \(Internals.typeName(into.entityClass)) from an already committed \(Internals.typeName(self))."
|
||||
@@ -114,7 +121,9 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
|
||||
- parameter objectIDs: the `NSManagedObjectID`s of the objects to delete
|
||||
*/
|
||||
public override func delete<S: Sequence>(objectIDs: S) where S.Iterator.Element: NSManagedObjectID {
|
||||
public override func delete<S: Sequence>(
|
||||
objectIDs: S
|
||||
) where S.Iterator.Element: NSManagedObjectID {
|
||||
|
||||
Internals.assert(
|
||||
!self.isCommitted,
|
||||
@@ -130,7 +139,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter object: the `ObjectRepresentation` representing an `NSManagedObject` or `CoreStoreObject` to be deleted
|
||||
- parameter objects: other `ObjectRepresentation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
|
||||
*/
|
||||
public override func delete<O: ObjectRepresentation>(_ object: O?, _ objects: O?...) {
|
||||
public override func delete<O: ObjectRepresentation>(
|
||||
_ object: O?,
|
||||
_ objects: O?...
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
!self.isCommitted,
|
||||
@@ -145,7 +157,9 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
|
||||
- parameter objects: the `ObjectRepresenation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
|
||||
*/
|
||||
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: ObjectRepresentation {
|
||||
public override func delete<S: Sequence>(
|
||||
_ objects: S
|
||||
) where S.Iterator.Element: ObjectRepresentation {
|
||||
|
||||
Internals.assert(
|
||||
!self.isCommitted,
|
||||
@@ -173,8 +187,13 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
)
|
||||
}
|
||||
|
||||
internal func autoCommit(_ completion: @escaping (_ hasChanges: Bool, _ error: CoreStoreError?) -> Void) {
|
||||
|
||||
internal func autoCommit(
|
||||
_ completion: @escaping (
|
||||
_ hasChanges: Bool,
|
||||
_ error: CoreStoreError?
|
||||
) -> Void
|
||||
) {
|
||||
|
||||
self.isCommitted = true
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
|
||||
@@ -41,25 +41,26 @@ extension BaseDataTransaction {
|
||||
*/
|
||||
public func importObject<O: ImportableObject>(
|
||||
_ into: Into<O>,
|
||||
source: O.ImportSource) throws -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsert(from: source, in: self)
|
||||
return object
|
||||
source: O.ImportSource
|
||||
) throws(any Swift.Error) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try Internals.autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsert(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,22 +72,23 @@ extension BaseDataTransaction {
|
||||
*/
|
||||
public func importObject<O: ImportableObject>(
|
||||
_ object: O,
|
||||
source: O.ImportSource) throws {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(object)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let entityType = object.runtimeType()
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return
|
||||
}
|
||||
try object.didInsert(from: source, in: self)
|
||||
source: O.ImportSource
|
||||
) throws(any Swift.Error) {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(object)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
try Internals.autoreleasepool {
|
||||
|
||||
let entityType = object.runtimeType()
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return
|
||||
}
|
||||
try object.didInsert(from: source, in: self)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,30 +101,31 @@ extension BaseDataTransaction {
|
||||
*/
|
||||
public func importObjects<O: ImportableObject, S: Sequence>(
|
||||
_ into: Into<O>,
|
||||
sourceArray: S) throws -> [O] where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
return try sourceArray.compactMap { (source) -> O? in
|
||||
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return try autoreleasepool {
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsert(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
sourceArray: S
|
||||
) throws(any Swift.Error) -> [O] where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try Internals.autoreleasepool {
|
||||
|
||||
return try sourceArray.compactMap { (source) -> O? in
|
||||
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return try autoreleasepool {
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsert(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,43 +138,44 @@ extension BaseDataTransaction {
|
||||
*/
|
||||
public func importUniqueObject<O: ImportableUniqueObject>(
|
||||
_ into: Into<O>,
|
||||
source: O.ImportSource) throws -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass
|
||||
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
|
||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||
|
||||
source: O.ImportSource
|
||||
) throws(any Swift.Error) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try Internals.autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass
|
||||
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
|
||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if let object = try self.fetchOne(From(entityType), Where<O>(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
||||
|
||||
guard entityType.shouldUpdate(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if let object = try self.fetchOne(From(entityType), Where<O>(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
||||
|
||||
guard entityType.shouldUpdate(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
try object.update(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
else {
|
||||
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = uniqueIDValue
|
||||
try object.didInsert(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
try object.update(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
else {
|
||||
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = uniqueIDValue
|
||||
try object.didInsert(from: source, in: self)
|
||||
return object
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,71 +192,74 @@ extension BaseDataTransaction {
|
||||
public func importUniqueObjects<O: ImportableUniqueObject, S: Sequence>(
|
||||
_ into: Into<O>,
|
||||
sourceArray: S,
|
||||
preProcess: @escaping (_ mapping: [O.UniqueIDType: O.ImportSource]) throws -> [O.UniqueIDType: O.ImportSource] = { $0 }) throws -> [O] where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass
|
||||
var importSourceByID = Dictionary<O.UniqueIDType, O.ImportSource>()
|
||||
let sortedIDs = try autoreleasepool {
|
||||
|
||||
return try sourceArray.compactMap { (source) -> O.UniqueIDType? in
|
||||
|
||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
importSourceByID[uniqueIDValue] = source // effectively replaces duplicate with the latest
|
||||
return uniqueIDValue
|
||||
}
|
||||
}
|
||||
|
||||
importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
|
||||
preProcess: @escaping (
|
||||
_ mapping: [O.UniqueIDType: O.ImportSource]
|
||||
) throws(any Swift.Error) -> [O.UniqueIDType: O.ImportSource] = { $0 }
|
||||
) throws(any Swift.Error) -> [O] where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
var existingObjectsByID = Dictionary<O.UniqueIDType, O>()
|
||||
try self
|
||||
.fetchAll(From(entityType), Where<O>(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))
|
||||
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
|
||||
|
||||
var processedObjectIDs = Set<O.UniqueIDType>()
|
||||
var result = [O]()
|
||||
|
||||
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
|
||||
|
||||
guard let source = importSourceByID[objectID] else {
|
||||
|
||||
continue
|
||||
}
|
||||
try autoreleasepool {
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
if let object = existingObjectsByID[objectID]
|
||||
?? self.context.insertedObjects
|
||||
.compactMap({ O.cs_matches(object: $0) ? O.cs_fromRaw(object: $0) : nil })
|
||||
.first(where: { $0.uniqueIDValue == objectID }) {
|
||||
|
||||
guard entityType.shouldUpdate(from: source, in: self) else {
|
||||
|
||||
return
|
||||
}
|
||||
try object.update(from: source, in: self)
|
||||
result.append(object)
|
||||
}
|
||||
else if entityType.shouldInsert(from: source, in: self) {
|
||||
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = objectID
|
||||
try object.didInsert(from: source, in: self)
|
||||
result.append(object)
|
||||
}
|
||||
processedObjectIDs.insert(objectID)
|
||||
return try Internals.autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass
|
||||
var importSourceByID = Dictionary<O.UniqueIDType, O.ImportSource>()
|
||||
let sortedIDs = try Internals.autoreleasepool {
|
||||
|
||||
return try sourceArray.compactMap { (source) -> O.UniqueIDType? in
|
||||
|
||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
importSourceByID[uniqueIDValue] = source // effectively replaces duplicate with the latest
|
||||
return uniqueIDValue
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
importSourceByID = try Internals.autoreleasepool { try preProcess(importSourceByID) }
|
||||
|
||||
var existingObjectsByID = Dictionary<O.UniqueIDType, O>()
|
||||
try self
|
||||
.fetchAll(From(entityType), Where<O>(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))
|
||||
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
|
||||
|
||||
var processedObjectIDs = Set<O.UniqueIDType>()
|
||||
var result = [O]()
|
||||
|
||||
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
|
||||
|
||||
guard let source = importSourceByID[objectID] else {
|
||||
|
||||
continue
|
||||
}
|
||||
try Internals.autoreleasepool {
|
||||
|
||||
if let object = existingObjectsByID[objectID]
|
||||
?? self.context.insertedObjects
|
||||
.compactMap({ O.cs_matches(object: $0) ? O.cs_fromRaw(object: $0) : nil })
|
||||
.first(where: { $0.uniqueIDValue == objectID }) {
|
||||
|
||||
guard entityType.shouldUpdate(from: source, in: self) else {
|
||||
|
||||
return
|
||||
}
|
||||
try object.update(from: source, in: self)
|
||||
result.append(object)
|
||||
}
|
||||
else if entityType.shouldInsert(from: source, in: self) {
|
||||
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = objectID
|
||||
try object.didInsert(from: source, in: self)
|
||||
result.append(object)
|
||||
}
|
||||
processedObjectIDs.insert(objectID)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<O>(_ from: From<O>, _ deleteClauses: DeleteClause...) throws -> Int {
|
||||
|
||||
public func deleteAll<O>(
|
||||
_ from: From<O>,
|
||||
_ deleteClauses: DeleteClause...
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -56,8 +59,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<O>(_ from: From<O>, _ deleteClauses: [DeleteClause]) throws -> Int {
|
||||
|
||||
public func deleteAll<O>(
|
||||
_ from: From<O>,
|
||||
_ deleteClauses: [DeleteClause]
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -74,14 +80,18 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
|
||||
|
||||
public func deleteAll<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete from a \(Internals.typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
return try self.context.deleteAll(clauseChain.from, clauseChain.fetchClauses)
|
||||
return try self.context.deleteAll(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -93,8 +103,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter object: a reference to the object created/fetched outside the transaction
|
||||
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject>(_ object: O) -> O? {
|
||||
|
||||
public func fetchExisting<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> O? {
|
||||
|
||||
return self.context.fetchExisting(object)
|
||||
}
|
||||
|
||||
@@ -104,8 +116,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject>(_ objectID: NSManagedObjectID) -> O? {
|
||||
|
||||
public func fetchExisting<O: DynamicObject>(
|
||||
_ objectID: NSManagedObjectID
|
||||
) -> O? {
|
||||
|
||||
return self.context.fetchExisting(objectID)
|
||||
}
|
||||
|
||||
@@ -115,8 +129,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter objects: an array of `DynamicObject`s created/fetched outside the transaction
|
||||
- returns: the `DynamicObject` array for objects that exists in the transaction
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objects: S) -> [O] where S.Iterator.Element == O {
|
||||
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objects: S
|
||||
) -> [O] where S.Iterator.Element == O {
|
||||
|
||||
return self.context.fetchExisting(objects)
|
||||
}
|
||||
|
||||
@@ -126,8 +142,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `DynamicObject` array for objects that exists in the transaction
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objectIDs: S) -> [O] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objectIDs: S
|
||||
) -> [O] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
return self.context.fetchExisting(objectIDs)
|
||||
}
|
||||
|
||||
@@ -139,8 +157,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> O? {
|
||||
|
||||
public func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -156,8 +177,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> O? {
|
||||
|
||||
public func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -178,8 +202,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> B.ObjectType? {
|
||||
|
||||
public func fetchOne<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ObjectType? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -195,8 +221,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [O] {
|
||||
|
||||
public func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -212,8 +241,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [O] {
|
||||
|
||||
public func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -234,8 +266,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [B.ObjectType] {
|
||||
|
||||
public func fetchAll<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [B.ObjectType] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -251,8 +285,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> Int {
|
||||
|
||||
public func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -268,8 +305,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> Int {
|
||||
|
||||
public func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -290,8 +330,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
|
||||
|
||||
public func fetchCount<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -307,8 +349,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -324,8 +369,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -346,8 +394,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -363,8 +413,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -380,8 +433,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -402,8 +458,10 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -425,8 +483,12 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: QueryClause...) throws -> U? {
|
||||
|
||||
public func queryValue<O, U: QueryableAttributeType>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, U>,
|
||||
_ queryClauses: QueryClause...
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -445,8 +507,12 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: [QueryClause]) throws -> U? {
|
||||
|
||||
public func queryValue<O, U: QueryableAttributeType>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, U>,
|
||||
_ queryClauses: [QueryClause]
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -469,13 +535,19 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query as specified by the `QueryChainableBuilderType`, or `nil` if no match was found.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> B.ResultType? where B.ResultType: QueryableAttributeType {
|
||||
|
||||
public func queryValue<B: QueryChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ResultType? where B.ResultType: QueryableAttributeType {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
|
||||
)
|
||||
return try self.context.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||
return try self.context.queryValue(
|
||||
clauseChain.from,
|
||||
clauseChain.select,
|
||||
clauseChain.queryClauses
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,8 +561,12 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
|
||||
|
||||
public func queryAttributes<O>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, NSDictionary>,
|
||||
_ queryClauses: QueryClause...
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -509,8 +585,12 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
|
||||
|
||||
public func queryAttributes<O>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, NSDictionary>,
|
||||
_ queryClauses: [QueryClause]
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -542,13 +622,19 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> [[String: Any]] where B.ResultType == NSDictionary {
|
||||
|
||||
public func queryAttributes<B: QueryChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [[String: Any]] where B.ResultType == NSDictionary {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
|
||||
)
|
||||
return try self.context.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||
return try self.context.queryAttributes(
|
||||
clauseChain.from,
|
||||
clauseChain.select,
|
||||
clauseChain.queryClauses
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -121,8 +121,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter object: the `NSManagedObject` or `CoreStoreObject` type to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||
*/
|
||||
public func edit<O: DynamicObject>(_ object: O?) -> O? {
|
||||
|
||||
public func edit<O: DynamicObject>(
|
||||
_ object: O?
|
||||
) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to update an entity of type \(Internals.typeName(object)) outside its designated queue."
|
||||
@@ -141,8 +143,11 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||
*/
|
||||
public func edit<O>(_ into: Into<O>, _ objectID: NSManagedObjectID) -> O? {
|
||||
|
||||
public func edit<O>(
|
||||
_ into: Into<O>,
|
||||
_ objectID: NSManagedObjectID
|
||||
) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to update an entity of type \(Internals.typeName(into.entityClass)) outside its designated queue."
|
||||
@@ -160,7 +165,9 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
|
||||
- parameter objectIDs: the `NSManagedObjectID`s of the objects to delete
|
||||
*/
|
||||
public func delete<S: Sequence>(objectIDs: S) where S.Iterator.Element: NSManagedObjectID {
|
||||
public func delete<S: Sequence>(
|
||||
objectIDs: S
|
||||
) where S.Iterator.Element: NSManagedObjectID {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -179,8 +186,11 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter object: the `ObjectRepresentation` representing an `NSManagedObject` or `CoreStoreObject` to be deleted
|
||||
- parameter objects: other `ObjectRepresentation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
|
||||
*/
|
||||
public func delete<O: ObjectRepresentation>(_ object: O?, _ objects: O?...) {
|
||||
|
||||
public func delete<O: ObjectRepresentation>(
|
||||
_ object: O?,
|
||||
_ objects: O?...
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete an entity outside its designated queue."
|
||||
@@ -193,8 +203,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
|
||||
- parameter objects: the `ObjectRepresenation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
|
||||
*/
|
||||
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: ObjectRepresentation {
|
||||
|
||||
public func delete<S: Sequence>(
|
||||
_ objects: S
|
||||
) where S.Iterator.Element: ObjectRepresentation {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete entities outside their designated queue."
|
||||
@@ -227,7 +239,9 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter object: the `DynamicObject` instance
|
||||
- returns: `true` if the object has any property values changed.
|
||||
*/
|
||||
public func objectHasPersistentChangedValues<O: DynamicObject>(_ object: O) -> Bool {
|
||||
public func objectHasPersistentChangedValues<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> Bool {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -246,8 +260,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter entity: the `DynamicObject` subclass to filter
|
||||
- returns: a `Set` of pending `DynamicObject`s of the specified type that were inserted to the transaction.
|
||||
*/
|
||||
public func insertedObjects<O: DynamicObject>(_ entity: O.Type) -> Set<O> {
|
||||
|
||||
public func insertedObjects<O: DynamicObject>(
|
||||
_ entity: O.Type
|
||||
) -> Set<O> {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to access inserted objects from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -283,8 +299,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter entity: the `DynamicObject` subclass to filter
|
||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
|
||||
*/
|
||||
public func insertedObjectIDs<O: DynamicObject>(_ entity: O.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
public func insertedObjectIDs<O: DynamicObject>(
|
||||
_ entity: O.Type
|
||||
) -> Set<NSManagedObjectID> {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to access inserted object IDs from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -302,8 +320,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter entity: the `DynamicObject` subclass to filter
|
||||
- returns: a `Set` of pending `DynamicObject`s of the specified type that were updated in the transaction.
|
||||
*/
|
||||
public func updatedObjects<O: DynamicObject>(_ entity: O.Type) -> Set<O> {
|
||||
|
||||
public func updatedObjects<O: DynamicObject>(
|
||||
_ entity: O.Type
|
||||
) -> Set<O> {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to access updated objects from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -339,8 +359,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter entity: the `DynamicObject` subclass to filter
|
||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
|
||||
*/
|
||||
public func updatedObjectIDs<O: DynamicObject>(_ entity: O.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
public func updatedObjectIDs<O: DynamicObject>(
|
||||
_ entity: O.Type
|
||||
) -> Set<NSManagedObjectID> {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to access updated object IDs from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -358,8 +380,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter entity: the `DynamicObject` subclass to filter
|
||||
- returns: a `Set` of pending `DynamicObject`s of the specified type that were deleted from the transaction.
|
||||
*/
|
||||
public func deletedObjects<O: DynamicObject>(_ entity: O.Type) -> Set<O> {
|
||||
|
||||
public func deletedObjects<O: DynamicObject>(
|
||||
_ entity: O.Type
|
||||
) -> Set<O> {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to access deleted objects from a \(Internals.typeName(self)) outside its designated queue."
|
||||
@@ -396,8 +420,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter entity: the `DynamicObject` subclass to filter
|
||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
||||
*/
|
||||
public func deletedObjectIDs<O: DynamicObject>(_ entity: O.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
public func deletedObjectIDs<O: DynamicObject>(
|
||||
_ entity: O.Type
|
||||
) -> Set<NSManagedObjectID> {
|
||||
|
||||
Internals.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to access deleted object IDs from a \(Internals.typeName(self)) outside its designated queue."
|
||||
|
||||
@@ -1073,13 +1073,21 @@ private func formattedDebugDescription(_ any: Any) -> String {
|
||||
return string
|
||||
}
|
||||
|
||||
private func createFormattedString(_ firstLine: String, _ lastLine: String, _ info: (key: String, value: Any)...) -> String {
|
||||
|
||||
private func createFormattedString(
|
||||
_ firstLine: String,
|
||||
_ lastLine: String,
|
||||
_ info: (key: String, value: Any)...
|
||||
) -> String {
|
||||
|
||||
return createFormattedString(firstLine, lastLine, info)
|
||||
}
|
||||
|
||||
private func createFormattedString(_ firstLine: String, _ lastLine: String, _ info: [(key: String, value: Any)]) -> String {
|
||||
|
||||
private func createFormattedString(
|
||||
_ firstLine: String,
|
||||
_ lastLine: String,
|
||||
_ info: [(key: String, value: Any)]
|
||||
) -> String {
|
||||
|
||||
var string = firstLine
|
||||
for (key, value) in info {
|
||||
|
||||
@@ -1102,8 +1110,11 @@ extension String {
|
||||
self = self.replacingOccurrences(of: "\n", with: "\n\(String.indention(level))")
|
||||
}
|
||||
|
||||
fileprivate mutating func appendDumpInfo(_ key: String, _ value: Any) {
|
||||
|
||||
fileprivate mutating func appendDumpInfo(
|
||||
_ key: String,
|
||||
_ value: Any
|
||||
) {
|
||||
|
||||
self.append("\n.\(key) = \(formattedValue(value));")
|
||||
}
|
||||
}
|
||||
@@ -1189,8 +1200,9 @@ extension NSAttributeDescription: CoreStoreDebugStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension NSAttributeType: @retroactive CustomDebugStringConvertible {}
|
||||
extension NSAttributeType: CoreStoreDebugStringConvertible {
|
||||
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
@@ -1215,8 +1227,14 @@ extension NSAttributeType: CoreStoreDebugStringConvertible {
|
||||
case .objectIDAttributeType: return ".objectIDAttributeType"
|
||||
case .UUIDAttributeType: return ".UUIDAttributeType"
|
||||
case .URIAttributeType: return ".URIAttributeType"
|
||||
|
||||
#if swift(>=5.9) // Xcode 15 (iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0)
|
||||
case .compositeAttributeType: return ".compositeAttributeType"
|
||||
|
||||
#endif
|
||||
|
||||
@unknown default:
|
||||
fatalError()
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1229,6 +1247,7 @@ extension Bundle: CoreStoreDebugStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension NSDeleteRule: @retroactive CustomDebugStringConvertible {}
|
||||
extension NSDeleteRule: CoreStoreDebugStringConvertible {
|
||||
|
||||
public var debugDescription: String {
|
||||
@@ -1393,6 +1412,7 @@ extension Optional: CoreStoreDebugStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension Result: @retroactive CustomDebugStringConvertible {}
|
||||
extension Result: CoreStoreDebugStringConvertible {
|
||||
|
||||
public var debugDescription: String {
|
||||
@@ -1419,6 +1439,7 @@ extension Result: CoreStoreDebugStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension Selector: @retroactive CustomDebugStringConvertible {}
|
||||
extension Selector: CoreStoreDebugStringConvertible {
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
@@ -33,7 +33,13 @@ extension Internals {
|
||||
// MARK: Internal
|
||||
|
||||
@inline(__always)
|
||||
internal static func log(_ level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
internal static func log(
|
||||
_ level: LogLevel,
|
||||
message: String,
|
||||
fileName: StaticString = #file,
|
||||
lineNumber: Int = #line,
|
||||
functionName: StaticString = #function
|
||||
) {
|
||||
|
||||
CoreStoreDefaults.logger.log(
|
||||
level: level,
|
||||
@@ -45,7 +51,13 @@ extension Internals {
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func log(_ error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
internal static func log(
|
||||
_ error: CoreStoreError,
|
||||
_ message: String,
|
||||
fileName: StaticString = #file,
|
||||
lineNumber: Int = #line,
|
||||
functionName: StaticString = #function
|
||||
) {
|
||||
|
||||
CoreStoreDefaults.logger.log(
|
||||
error: error,
|
||||
@@ -57,7 +69,13 @@ extension Internals {
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
internal static func assert(
|
||||
_ condition: @autoclosure () -> Bool,
|
||||
_ message: @autoclosure () -> String,
|
||||
fileName: StaticString = #file,
|
||||
lineNumber: Int = #line,
|
||||
functionName: StaticString = #function
|
||||
) {
|
||||
|
||||
CoreStoreDefaults.logger.assert(
|
||||
condition(),
|
||||
@@ -69,7 +87,12 @@ extension Internals {
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func abort(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) -> Never {
|
||||
internal static func abort(
|
||||
_ message: String,
|
||||
fileName: StaticString = #file,
|
||||
lineNumber: Int = #line,
|
||||
functionName: StaticString = #function
|
||||
) -> Never {
|
||||
|
||||
CoreStoreDefaults.logger.abort(
|
||||
message,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,8 +56,14 @@ public protocol CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
|
||||
|
||||
func log(
|
||||
level: LogLevel,
|
||||
message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
)
|
||||
|
||||
/**
|
||||
Handles errors sent by the `CoreStore` framework.
|
||||
|
||||
@@ -67,8 +73,14 @@ public protocol CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
|
||||
|
||||
func log(
|
||||
error: CoreStoreError,
|
||||
message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
)
|
||||
|
||||
/**
|
||||
Handles assertions made throughout the `CoreStore` framework.
|
||||
|
||||
@@ -78,8 +90,14 @@ public protocol CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
|
||||
|
||||
func assert(
|
||||
_ condition: @autoclosure () -> Bool,
|
||||
message: @autoclosure () -> String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
)
|
||||
|
||||
/**
|
||||
Handles fatal errors made throughout the `CoreStore` framework. The app wil terminate after this method is called.
|
||||
- Important: Implementers may guarantee that the function doesn't return, either by calling another `Never` function such as `fatalError()` or `abort()`, or by raising an exception. If the implementation does not terminate the app, CoreStore will call an internal `fatalError()` to do so.
|
||||
@@ -89,13 +107,23 @@ public protocol CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
|
||||
func abort(
|
||||
_ message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
)
|
||||
}
|
||||
|
||||
extension CoreStoreLogger {
|
||||
|
||||
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
public func abort(
|
||||
_ message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
) {
|
||||
|
||||
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,17 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - DynamicObject where Self: CoreStoreObject
|
||||
|
||||
extension DynamicObject where Self: CoreStoreObject {
|
||||
|
||||
public func observe<O, V>(_ keyPath: KeyPath<Self, FieldContainer<O>.Stored<V>>, options: NSKeyValueObservingOptions = [], changeHandler: @escaping (Self, CoreStoreObjectValueDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
// MARK: Public
|
||||
|
||||
public func observe<O, V>(
|
||||
_ keyPath: KeyPath<Self, FieldContainer<O>.Stored<V>>,
|
||||
options: NSKeyValueObservingOptions = [],
|
||||
changeHandler: @escaping (Self, CoreStoreObjectValueDiff<V>) -> Void
|
||||
) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
@@ -70,180 +78,6 @@ public protocol CoreStoreObjectKeyValueObservation: AnyObject {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ValueContainer.Required
|
||||
|
||||
extension ValueContainer.Required {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectValueDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ValueContainer.Optional
|
||||
|
||||
extension ValueContainer.Optional {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectValueDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - TransformableContainer.Required
|
||||
|
||||
extension TransformableContainer.Required {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectTransformableDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - TransformableContainer.Optional
|
||||
|
||||
extension TransformableContainer.Optional {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectTransformableDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipContainer.ToOne
|
||||
|
||||
extension RelationshipContainer.ToOne {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectObjectDiff<D>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
keyPath: self.keyPath,
|
||||
callback: { (object, kind, newValue, oldValue, _, isPrior) in
|
||||
|
||||
let notification = CoreStoreObjectObjectDiff<D>(
|
||||
kind: kind,
|
||||
newNativeValue: newValue as! CoreStoreManagedObject?,
|
||||
oldNativeValue: oldValue as! CoreStoreManagedObject?,
|
||||
isPrior: isPrior
|
||||
)
|
||||
changeHandler(
|
||||
O.cs_fromRaw(object: object),
|
||||
notification
|
||||
)
|
||||
}
|
||||
)
|
||||
result.start(options)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipContainer.ToManyUnordered
|
||||
|
||||
extension RelationshipContainer.ToManyUnordered {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectUnorderedDiff<D>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
keyPath: self.keyPath,
|
||||
callback: { (object, kind, newValue, oldValue, _, isPrior) in
|
||||
|
||||
let notification = CoreStoreObjectUnorderedDiff<D>(
|
||||
kind: kind,
|
||||
newNativeValue: newValue as! NSOrderedSet?,
|
||||
oldNativeValue: oldValue as! NSOrderedSet?,
|
||||
isPrior: isPrior
|
||||
)
|
||||
changeHandler(
|
||||
O.cs_fromRaw(object: object),
|
||||
notification
|
||||
)
|
||||
}
|
||||
)
|
||||
result.start(options)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipContainer.ToManyOrdered
|
||||
|
||||
extension RelationshipContainer.ToManyOrdered {
|
||||
|
||||
/**
|
||||
Observes changes in the receiver value. When the returned `CoreStoreObjectKeyValueObservation` is deinited or invalidated, it will stop observing.
|
||||
|
||||
- parameter options: The flags indicating which values to include in the change dictionary.
|
||||
- parameter: changeHandler: The closure called when the value is updated.
|
||||
*/
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectOrderedDiff<D>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
keyPath: self.keyPath,
|
||||
callback: { (object, kind, newValue, oldValue, indexes, isPrior) in
|
||||
|
||||
let notification = CoreStoreObjectOrderedDiff<D>(
|
||||
kind: kind,
|
||||
newNativeValue: newValue as! NSArray?,
|
||||
oldNativeValue: oldValue as! NSArray?,
|
||||
indexes: indexes ?? IndexSet(),
|
||||
isPrior: isPrior
|
||||
)
|
||||
changeHandler(
|
||||
O.cs_fromRaw(object: object),
|
||||
notification
|
||||
)
|
||||
}
|
||||
)
|
||||
result.start(options)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CoreStoreObjectValueDiff
|
||||
|
||||
/**
|
||||
@@ -360,7 +194,12 @@ public final class CoreStoreObjectObjectDiff<D: CoreStoreObject> {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate init(kind: NSKeyValueChange, newNativeValue: CoreStoreManagedObject?, oldNativeValue: CoreStoreManagedObject?, isPrior: Bool) {
|
||||
fileprivate init(
|
||||
kind: NSKeyValueChange,
|
||||
newNativeValue: CoreStoreManagedObject?,
|
||||
oldNativeValue: CoreStoreManagedObject?,
|
||||
isPrior: Bool
|
||||
) {
|
||||
|
||||
self.kind = kind
|
||||
self.newNativeValue = newNativeValue
|
||||
@@ -406,7 +245,12 @@ public final class CoreStoreObjectUnorderedDiff<D: CoreStoreObject> {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate init(kind: NSKeyValueChange, newNativeValue: NSOrderedSet?, oldNativeValue: NSOrderedSet?, isPrior: Bool) {
|
||||
fileprivate init(
|
||||
kind: NSKeyValueChange,
|
||||
newNativeValue: NSOrderedSet?,
|
||||
oldNativeValue: NSOrderedSet?,
|
||||
isPrior: Bool
|
||||
) {
|
||||
|
||||
self.kind = kind
|
||||
self.newNativeValue = newNativeValue ?? []
|
||||
@@ -457,7 +301,13 @@ public final class CoreStoreObjectOrderedDiff<D: CoreStoreObject> {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate init(kind: NSKeyValueChange, newNativeValue: NSArray?, oldNativeValue: NSArray?, indexes: IndexSet, isPrior: Bool) {
|
||||
fileprivate init(
|
||||
kind: NSKeyValueChange,
|
||||
newNativeValue: NSArray?,
|
||||
oldNativeValue: NSArray?,
|
||||
indexes: IndexSet,
|
||||
isPrior: Bool
|
||||
) {
|
||||
|
||||
self.kind = kind
|
||||
self.newNativeValue = newNativeValue ?? []
|
||||
@@ -536,7 +386,18 @@ fileprivate final class _CoreStoreObjectKeyValueObservation: NSObject, CoreStore
|
||||
// MARK: FilePrivate
|
||||
|
||||
@nonobjc
|
||||
fileprivate init(object: CoreStoreManagedObject, keyPath: KeyPathString, callback: @escaping (_ object: CoreStoreManagedObject, _ kind: NSKeyValueChange, _ newValue: Any?, _ oldValue: Any?, _ indexes: IndexSet?, _ isPrior: Bool) -> Void) {
|
||||
fileprivate init(
|
||||
object: CoreStoreManagedObject,
|
||||
keyPath: KeyPathString,
|
||||
callback: @escaping (
|
||||
_ object: CoreStoreManagedObject,
|
||||
_ kind: NSKeyValueChange,
|
||||
_ newValue: Any?,
|
||||
_ oldValue: Any?,
|
||||
_ indexes: IndexSet?,
|
||||
_ isPrior: Bool
|
||||
) -> Void
|
||||
) {
|
||||
|
||||
let _ = _CoreStoreObjectKeyValueObservation.swizzler
|
||||
self.keyPath = keyPath
|
||||
@@ -547,12 +408,19 @@ fileprivate final class _CoreStoreObjectKeyValueObservation: NSObject, CoreStore
|
||||
@nonobjc
|
||||
fileprivate func start(_ options: NSKeyValueObservingOptions) {
|
||||
|
||||
self.object?.addObserver(self, forKeyPath: self.keyPath, options: options, context: nil)
|
||||
self.object?
|
||||
.addObserver(
|
||||
self,
|
||||
forKeyPath: self.keyPath,
|
||||
options: options,
|
||||
context: nil
|
||||
)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.object?.removeObserver(self, forKeyPath: self.keyPath, context: nil)
|
||||
self.object?
|
||||
.removeObserver(self, forKeyPath: self.keyPath, context: nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -561,7 +429,8 @@ fileprivate final class _CoreStoreObjectKeyValueObservation: NSObject, CoreStore
|
||||
@nonobjc
|
||||
public func invalidate() {
|
||||
|
||||
self.object?.removeObserver(self, forKeyPath: self.keyPath, context: nil)
|
||||
self.object?
|
||||
.removeObserver(self, forKeyPath: self.keyPath, context: nil)
|
||||
self.object = nil
|
||||
}
|
||||
|
||||
@@ -575,11 +444,17 @@ fileprivate final class _CoreStoreObjectKeyValueObservation: NSObject, CoreStore
|
||||
let bridgeClass: AnyClass = _CoreStoreObjectKeyValueObservation.self
|
||||
let rootObserveImpl = class_getInstanceMethod(
|
||||
bridgeClass,
|
||||
#selector(_CoreStoreObjectKeyValueObservation.observeValue(forKeyPath:of:change:context:))
|
||||
#selector(
|
||||
_CoreStoreObjectKeyValueObservation
|
||||
.observeValue(forKeyPath:of:change:context:)
|
||||
)
|
||||
)!
|
||||
let swapObserveImpl = class_getInstanceMethod(
|
||||
bridgeClass,
|
||||
#selector(_CoreStoreObjectKeyValueObservation._cs_swizzle_me_observeValue(forKeyPath:of:change:context:))
|
||||
#selector(
|
||||
_CoreStoreObjectKeyValueObservation
|
||||
._cs_swizzle_me_observeValue(forKeyPath:of:change:context:)
|
||||
)
|
||||
)!
|
||||
method_exchangeImplementations(rootObserveImpl, swapObserveImpl)
|
||||
return nil
|
||||
@@ -589,21 +464,33 @@ fileprivate final class _CoreStoreObjectKeyValueObservation: NSObject, CoreStore
|
||||
private weak var object: CoreStoreManagedObject?
|
||||
|
||||
@nonobjc
|
||||
private let callback: (_ object: CoreStoreManagedObject, _ kind: NSKeyValueChange, _ newValue: Any?, _ oldValue: Any?, _ indexes: IndexSet?, _ isPrior: Bool) -> Void
|
||||
private let callback: (
|
||||
_ object: CoreStoreManagedObject,
|
||||
_ kind: NSKeyValueChange,
|
||||
_ newValue: Any?,
|
||||
_ oldValue: Any?,
|
||||
_ indexes: IndexSet?,
|
||||
_ isPrior: Bool
|
||||
) -> Void
|
||||
|
||||
@nonobjc
|
||||
private let keyPath: KeyPathString
|
||||
|
||||
@objc
|
||||
private dynamic func _cs_swizzle_me_observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSString: Any]?, context: UnsafeMutableRawPointer?) {
|
||||
private dynamic func _cs_swizzle_me_observeValue(
|
||||
forKeyPath keyPath: String?,
|
||||
of object: Any?,
|
||||
change: [NSString: Any]?,
|
||||
context: UnsafeMutableRawPointer?
|
||||
) {
|
||||
|
||||
guard
|
||||
let object = object as? CoreStoreManagedObject,
|
||||
object == self.object,
|
||||
let change = change
|
||||
else {
|
||||
else {
|
||||
|
||||
return
|
||||
return
|
||||
}
|
||||
let rawKind: UInt = change[NSKeyValueChangeKey.kindKey.rawValue as NSString] as! UInt
|
||||
self.callback(
|
||||
@@ -616,3 +503,138 @@ fileprivate final class _CoreStoreObjectKeyValueObservation: NSObject, CoreStore
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension ValueContainer.Required {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectValueDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension ValueContainer.Optional {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectValueDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension TransformableContainer.Required {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectTransformableDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension TransformableContainer.Optional {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectTransformableDiff<V>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
return self.observe(with: options, changeHandler: changeHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension RelationshipContainer.ToOne {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectObjectDiff<D>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
keyPath: self.keyPath,
|
||||
callback: { (object, kind, newValue, oldValue, _, isPrior) in
|
||||
|
||||
let notification = CoreStoreObjectObjectDiff<D>(
|
||||
kind: kind,
|
||||
newNativeValue: newValue as! CoreStoreManagedObject?,
|
||||
oldNativeValue: oldValue as! CoreStoreManagedObject?,
|
||||
isPrior: isPrior
|
||||
)
|
||||
changeHandler(
|
||||
O.cs_fromRaw(object: object),
|
||||
notification
|
||||
)
|
||||
}
|
||||
)
|
||||
result.start(options)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension RelationshipContainer.ToManyUnordered {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectUnorderedDiff<D>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
keyPath: self.keyPath,
|
||||
callback: { (object, kind, newValue, oldValue, _, isPrior) in
|
||||
|
||||
let notification = CoreStoreObjectUnorderedDiff<D>(
|
||||
kind: kind,
|
||||
newNativeValue: newValue as! NSOrderedSet?,
|
||||
oldNativeValue: oldValue as! NSOrderedSet?,
|
||||
isPrior: isPrior
|
||||
)
|
||||
changeHandler(
|
||||
O.cs_fromRaw(object: object),
|
||||
notification
|
||||
)
|
||||
}
|
||||
)
|
||||
result.start(options)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension RelationshipContainer.ToManyOrdered {
|
||||
|
||||
public func observe(options: NSKeyValueObservingOptions = [], changeHandler: @escaping (O, CoreStoreObjectOrderedDiff<D>) -> Void) -> CoreStoreObjectKeyValueObservation {
|
||||
|
||||
let result = _CoreStoreObjectKeyValueObservation(
|
||||
object: self.rawObject!,
|
||||
keyPath: self.keyPath,
|
||||
callback: { (object, kind, newValue, oldValue, indexes, isPrior) in
|
||||
|
||||
let notification = CoreStoreObjectOrderedDiff<D>(
|
||||
kind: kind,
|
||||
newNativeValue: newValue as! NSArray?,
|
||||
oldNativeValue: oldValue as! NSArray?,
|
||||
indexes: indexes ?? IndexSet(),
|
||||
isPrior: isPrior
|
||||
)
|
||||
changeHandler(
|
||||
O.cs_fromRaw(object: object),
|
||||
notification
|
||||
)
|
||||
}
|
||||
)
|
||||
result.start(options)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,15 @@ extension FieldContainer.Stored {
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.nickname == "John" }))
|
||||
```
|
||||
*/
|
||||
public static func == (_ attribute: Self, _ value: V) -> Where<O> {
|
||||
public static func == (
|
||||
_ attribute: Self,
|
||||
_ value: V
|
||||
) -> Where<O> {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
return Where(
|
||||
attribute.keyPath,
|
||||
isEqualTo: value
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,9 +53,15 @@ extension FieldContainer.Stored {
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.nickname != "John" }))
|
||||
```
|
||||
*/
|
||||
public static func != (_ attribute: Self, _ value: V) -> Where<O> {
|
||||
public static func != (
|
||||
_ attribute: Self,
|
||||
_ value: V
|
||||
) -> Where<O> {
|
||||
|
||||
return !Where(attribute.keyPath, isEqualTo: value)
|
||||
return !Where(
|
||||
attribute.keyPath,
|
||||
isEqualTo: value
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,9 +70,16 @@ extension FieldContainer.Stored {
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age < 20 }))
|
||||
```
|
||||
*/
|
||||
public static func < (_ attribute: Self, _ value: V) -> Where<O> {
|
||||
public static func < (
|
||||
_ attribute: Self,
|
||||
_ value: V
|
||||
) -> Where<O> {
|
||||
|
||||
return Where("%K < %@", attribute.keyPath, value.cs_toFieldStoredNativeType() as Any)
|
||||
return Where(
|
||||
"%K < %@",
|
||||
attribute.keyPath,
|
||||
value.cs_toFieldStoredNativeType() as Any
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,9 +88,16 @@ extension FieldContainer.Stored {
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age > 20 }))
|
||||
```
|
||||
*/
|
||||
public static func > (_ attribute: Self, _ value: V) -> Where<O> {
|
||||
public static func > (
|
||||
_ attribute: Self,
|
||||
_ value: V
|
||||
) -> Where<O> {
|
||||
|
||||
return Where("%K > %@", attribute.keyPath, value.cs_toFieldStoredNativeType() as Any)
|
||||
return Where(
|
||||
"%K > %@",
|
||||
attribute.keyPath,
|
||||
value.cs_toFieldStoredNativeType() as Any
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,9 +106,16 @@ extension FieldContainer.Stored {
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age <= 20 }))
|
||||
```
|
||||
*/
|
||||
public static func <= (_ attribute: Self, _ value: V) -> Where<O> {
|
||||
public static func <= (
|
||||
_ attribute: Self,
|
||||
_ value: V
|
||||
) -> Where<O> {
|
||||
|
||||
return Where("%K <= %@", attribute.keyPath, value.cs_toFieldStoredNativeType() as Any)
|
||||
return Where(
|
||||
"%K <= %@",
|
||||
attribute.keyPath,
|
||||
value.cs_toFieldStoredNativeType() as Any
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,9 +124,16 @@ extension FieldContainer.Stored {
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age >= 20 }))
|
||||
```
|
||||
*/
|
||||
public static func >= (_ attribute: Self, _ value: V) -> Where<O> {
|
||||
public static func >= (
|
||||
_ attribute: Self,
|
||||
_ value: V
|
||||
) -> Where<O> {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value.cs_toFieldStoredNativeType() as Any)
|
||||
return Where(
|
||||
"%K >= %@",
|
||||
attribute.keyPath,
|
||||
value.cs_toFieldStoredNativeType() as Any
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,127 +142,76 @@ extension FieldContainer.Stored {
|
||||
let dog = dataStack.fetchOne(From<Dog>().where({ ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname }))
|
||||
```
|
||||
*/
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: Self) -> Where<O> where S.Iterator.Element == V {
|
||||
public static func ~= <S: Sequence>(
|
||||
_ sequence: S,
|
||||
_ attribute: Self
|
||||
) -> Where<O> where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
return Where(
|
||||
attribute.keyPath,
|
||||
isMemberOf: sequence
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ValueContainer.Required
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension ValueContainer.Required {
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.nickname == "John" }))
|
||||
```
|
||||
*/
|
||||
public static func == (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is not equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.nickname != "John" }))
|
||||
```
|
||||
*/
|
||||
public static func != (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
|
||||
|
||||
return !Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is less than a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age < 20 }))
|
||||
```
|
||||
*/
|
||||
public static func < (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
|
||||
|
||||
return Where("%K < %@", attribute.keyPath, value.cs_toQueryableNativeType())
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is greater than a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age > 20 }))
|
||||
```
|
||||
*/
|
||||
public static func > (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
|
||||
|
||||
return Where("%K > %@", attribute.keyPath, value.cs_toQueryableNativeType())
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is less than or equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age <= 20 }))
|
||||
```
|
||||
*/
|
||||
public static func <= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
|
||||
|
||||
return Where("%K <= %@", attribute.keyPath, value.cs_toQueryableNativeType())
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is greater than or equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age >= 20 }))
|
||||
```
|
||||
*/
|
||||
public static func >= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value.cs_toQueryableNativeType())
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by checking if a sequence contains the value of a property
|
||||
```
|
||||
let dog = dataStack.fetchOne(From<Dog>().where({ ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname }))
|
||||
```
|
||||
*/
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Required<V>) -> Where<O> where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ValueContainer.Optional
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension ValueContainer.Optional {
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.nickname == "John" }))
|
||||
```
|
||||
*/
|
||||
public static func == (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
|
||||
|
||||
return Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is not equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.nickname != "John" }))
|
||||
```
|
||||
*/
|
||||
public static func != (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
|
||||
|
||||
return !Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is less than a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age < 20 }))
|
||||
```
|
||||
*/
|
||||
public static func < (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
|
||||
|
||||
if let value = value {
|
||||
@@ -235,12 +224,6 @@ extension ValueContainer.Optional {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is greater than a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age > 20 }))
|
||||
```
|
||||
*/
|
||||
public static func > (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
|
||||
|
||||
if let value = value {
|
||||
@@ -253,12 +236,6 @@ extension ValueContainer.Optional {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is less than or equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age <= 20 }))
|
||||
```
|
||||
*/
|
||||
public static func <= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
|
||||
|
||||
if let value = value {
|
||||
@@ -271,12 +248,6 @@ extension ValueContainer.Optional {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is greater than or equal to a value
|
||||
```
|
||||
let person = dataStack.fetchOne(From<Person>().where({ $0.age >= 20 }))
|
||||
```
|
||||
*/
|
||||
public static func >= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
|
||||
|
||||
if let value = value {
|
||||
@@ -289,51 +260,27 @@ extension ValueContainer.Optional {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by checking if a sequence contains the value of a property
|
||||
```
|
||||
let dog = dataStack.fetchOne(From<Dog>().where({ ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname }))
|
||||
```
|
||||
*/
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Optional<V>) -> Where<O> where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipContainer.ToOne
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension RelationshipContainer.ToOne {
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is equal to a value
|
||||
```
|
||||
let dog = dataStack.fetchOne(From<Dog>().where({ $0.master == me }))
|
||||
```
|
||||
*/
|
||||
public static func == (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where<O> {
|
||||
|
||||
return Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if a property is not equal to a value
|
||||
```
|
||||
let dog = dataStack.fetchOne(From<Dog>().where({ $0.master != me }))
|
||||
```
|
||||
*/
|
||||
public static func != (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where<O> {
|
||||
|
||||
return !Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by checking if a sequence contains the value of a property
|
||||
```
|
||||
let dog = dataStack.fetchOne(From<Dog>().where({ [john, joe, bob] ~= $0.master }))
|
||||
```
|
||||
*/
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ relationship: RelationshipContainer<O>.ToOne<D>) -> Where<O> where S.Iterator.Element == D {
|
||||
|
||||
return Where(relationship.keyPath, isMemberOf: sequence)
|
||||
|
||||
@@ -129,7 +129,10 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
|
||||
internal class func metaProperties(includeSuperclasses: Bool) -> [PropertyProtocol] {
|
||||
|
||||
func keyPaths(_ allKeyPaths: inout [PropertyProtocol], for dynamicType: CoreStoreObject.Type) {
|
||||
func keyPaths(
|
||||
_ allKeyPaths: inout [PropertyProtocol],
|
||||
for dynamicType: CoreStoreObject.Type
|
||||
) {
|
||||
|
||||
allKeyPaths.append(contentsOf: dynamicType.meta.propertyProtocolsByName())
|
||||
guard
|
||||
@@ -151,7 +154,10 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func containsLegacyAttributes(mirror: Mirror, object: CoreStoreObject) -> Bool {
|
||||
private func containsLegacyAttributes(
|
||||
mirror: Mirror,
|
||||
object: CoreStoreObject
|
||||
) -> Bool {
|
||||
|
||||
if let superclassMirror = mirror.superclassMirror,
|
||||
self.containsLegacyAttributes(mirror: superclassMirror, object: object) {
|
||||
@@ -175,8 +181,11 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
return false
|
||||
}
|
||||
|
||||
private func registerReceiver(mirror: Mirror, object: CoreStoreObject) {
|
||||
|
||||
private func registerReceiver(
|
||||
mirror: Mirror,
|
||||
object: CoreStoreObject
|
||||
) {
|
||||
|
||||
if let superclassMirror = mirror.superclassMirror {
|
||||
|
||||
self.registerReceiver(
|
||||
|
||||
@@ -94,8 +94,12 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
- parameter entities: an array of `Entity<T>` pertaining to all `CoreStoreObject` subclasses to be added to the schema version.
|
||||
- parameter versionLock: an optional list of `VersionLock` hashes for each entity name in the `entities` array. If any `DynamicEntity` doesn't match its version lock hash, an assertion will be raised.
|
||||
*/
|
||||
public convenience init(modelVersion: ModelVersion, entities: [DynamicEntity], versionLock: VersionLock? = nil) {
|
||||
|
||||
public convenience init(
|
||||
modelVersion: ModelVersion,
|
||||
entities: [DynamicEntity],
|
||||
versionLock: VersionLock? = nil
|
||||
) {
|
||||
|
||||
var entityConfigurations: [DynamicEntity: Set<String>] = [:]
|
||||
for entity in entities {
|
||||
|
||||
@@ -138,8 +142,12 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
- parameter entityConfigurations: a dictionary with `Entity<T>` pertaining to all `CoreStoreObject` subclasses and the corresponding list of "Configurations" they should be added to. To add an entity only to the default configuration, assign an empty set to its configurations list. Note that regardless of the set configurations, all entities will be added to the default configuration.
|
||||
- parameter versionLock: an optional list of `VersionLock` hashes for each entity name in the `entities` array. If any `DynamicEntity` doesn't match its version lock hash, an assertion will be raised.
|
||||
*/
|
||||
public required init(modelVersion: ModelVersion, entityConfigurations: [DynamicEntity: Set<String>], versionLock: VersionLock? = nil) {
|
||||
|
||||
public required init(
|
||||
modelVersion: ModelVersion,
|
||||
entityConfigurations: [DynamicEntity: Set<String>],
|
||||
versionLock: VersionLock? = nil
|
||||
) {
|
||||
|
||||
var actualEntitiesByConfiguration: [String: Set<DynamicEntity>] = [:]
|
||||
for (entity, configurations) in entityConfigurations {
|
||||
|
||||
@@ -305,7 +313,10 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
)
|
||||
}
|
||||
|
||||
private static func firstPassCreateEntityDescription(from entity: DynamicEntity, in modelVersion: ModelVersion) -> (
|
||||
private static func firstPassCreateEntityDescription(
|
||||
from entity: DynamicEntity,
|
||||
in modelVersion: ModelVersion
|
||||
) -> (
|
||||
entity: NSEntityDescription,
|
||||
customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter],
|
||||
customInitializerByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomInitializer],
|
||||
@@ -323,8 +334,11 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
var customInitialValuesByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomInitializer] = [:]
|
||||
var customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter] = [:]
|
||||
var fieldCoders: [KeyPathString: Internals.AnyFieldCoder] = [:]
|
||||
func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] {
|
||||
|
||||
|
||||
func createProperties(
|
||||
for type: CoreStoreObject.Type
|
||||
) -> [NSPropertyDescription] {
|
||||
|
||||
var propertyDescriptions: [NSPropertyDescription] = []
|
||||
for property in type.metaProperties(includeSuperclasses: false) {
|
||||
|
||||
@@ -425,15 +439,20 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
)
|
||||
}
|
||||
|
||||
private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) {
|
||||
|
||||
private static func secondPassConnectRelationshipAttributes(
|
||||
for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]
|
||||
) {
|
||||
|
||||
var relationshipsByNameByEntity: [DynamicEntity: [String: NSRelationshipDescription]] = [:]
|
||||
for (entity, entityDescription) in entityDescriptionsByEntity {
|
||||
|
||||
relationshipsByNameByEntity[entity] = entityDescription.relationshipsByName
|
||||
}
|
||||
func findEntity(for type: CoreStoreObject.Type) -> DynamicEntity {
|
||||
|
||||
|
||||
func findEntity(
|
||||
for type: CoreStoreObject.Type
|
||||
) -> DynamicEntity {
|
||||
|
||||
var matchedEntities: Set<DynamicEntity> = []
|
||||
for (entity, _) in entityDescriptionsByEntity where entity.type == type {
|
||||
|
||||
@@ -457,8 +476,11 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
}
|
||||
}
|
||||
|
||||
func findInverseRelationshipMatching(destinationEntity: DynamicEntity, destinationKeyPath: String) -> NSRelationshipDescription {
|
||||
|
||||
func findInverseRelationshipMatching(
|
||||
destinationEntity: DynamicEntity,
|
||||
destinationKeyPath: String
|
||||
) -> NSRelationshipDescription {
|
||||
|
||||
for case (destinationKeyPath, let relationshipDescription) in relationshipsByNameByEntity[destinationEntity]! {
|
||||
|
||||
return relationshipDescription
|
||||
@@ -537,10 +559,15 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
}
|
||||
}
|
||||
|
||||
private static func thirdPassConnectInheritanceTreeAndIndexes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) {
|
||||
|
||||
func connectBaseEntity(mirror: Mirror, entityDescription: NSEntityDescription) {
|
||||
|
||||
private static func thirdPassConnectInheritanceTreeAndIndexes(
|
||||
for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]
|
||||
) {
|
||||
|
||||
func connectBaseEntity(
|
||||
mirror: Mirror,
|
||||
entityDescription: NSEntityDescription
|
||||
) {
|
||||
|
||||
guard let superclassMirror = mirror.superclassMirror,
|
||||
let superType = superclassMirror.subjectType as? CoreStoreObject.Type,
|
||||
superType != CoreStoreObject.self else {
|
||||
@@ -636,13 +663,6 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
}
|
||||
let managedObjectClass: AnyClass = className.withCString {
|
||||
|
||||
// Xcode 10.1+ users: You may find this comment due to a crash while debugging on an iPhone XR device (or any A12 device).
|
||||
// This is a known issue that should not occur in archived builds, as the AppStore strips away arm64e build architectures from the binary. So while it crashes on DEBUG, it shouldn't be an issue for live users.
|
||||
// In the meantime, please submit a bug report to Apple and refer to similar discussions here:
|
||||
// - https://github.com/realm/realm-cocoa/issues/6013
|
||||
// - https://github.com/wordpress-mobile/WordPress-iOS/pull/10400
|
||||
// - https://github.com/JohnEstropia/CoreStore/issues/291
|
||||
// If you wish to debug with A12 devices, please use Xcode 10.0 for now.
|
||||
return objc_allocateClassPair(superClass, $0, 0)!
|
||||
}
|
||||
defer {
|
||||
|
||||
@@ -51,8 +51,12 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
- parameter destinationVersion: the destination model version for the mapping
|
||||
- parameter entityMappings: a list of `CustomMapping`s. Mappings of entities with no `CustomMapping` provided will be automatically calculated if possible. Any conflicts or ambiguity will raise an assertion.
|
||||
*/
|
||||
public required init(from sourceVersion: ModelVersion, to destinationVersion: ModelVersion, entityMappings: Set<CustomMapping> = []) {
|
||||
|
||||
public required init(
|
||||
from sourceVersion: ModelVersion,
|
||||
to destinationVersion: ModelVersion,
|
||||
entityMappings: Set<CustomMapping> = []
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
Internals.with {
|
||||
|
||||
@@ -101,13 +105,19 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
- parameter sourceObject: a proxy object representing the source entity. The properties can be accessed via keyPath.
|
||||
- parameter createDestinationObject: the closure to create the object for the destination entity. The `CustomMapping.inferredTransformation` method can be used directly as the `transformer` if the changes can be inferred (i.e. lightweight). The object is created lazily and executing the closure multiple times will return the same instance. The destination object's properties can be accessed and updated via keyPath.
|
||||
*/
|
||||
public typealias Transformer = (_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void
|
||||
|
||||
public typealias Transformer = (
|
||||
_ sourceObject: UnsafeSourceObject,
|
||||
_ createDestinationObject: () -> UnsafeDestinationObject
|
||||
) throws(any Swift.Error) -> Void
|
||||
|
||||
/**
|
||||
The `CustomMapping.inferredTransformation` method can be used directly as the `transformer` if the changes can be inferred (i.e. lightweight).
|
||||
*/
|
||||
public static func inferredTransformation(_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void {
|
||||
|
||||
public static func inferredTransformation(
|
||||
_ sourceObject: UnsafeSourceObject,
|
||||
_ createDestinationObject: () -> UnsafeDestinationObject
|
||||
) throws(any Swift.Error) {
|
||||
|
||||
let destinationObject = createDestinationObject()
|
||||
destinationObject.enumerateAttributes { (attribute, sourceAttribute) in
|
||||
|
||||
@@ -343,8 +353,15 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
// MARK: SchemaMappingProvider
|
||||
|
||||
public func cs_createMappingModel(from sourceSchema: DynamicSchema, to destinationSchema: DynamicSchema, storage: LocalStorage) throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
|
||||
|
||||
public func cs_createMappingModel(
|
||||
from sourceSchema: DynamicSchema,
|
||||
to destinationSchema: DynamicSchema,
|
||||
storage: LocalStorage
|
||||
) throws(CoreStoreError) -> (
|
||||
mappingModel: NSMappingModel,
|
||||
migrationType: MigrationType
|
||||
) {
|
||||
|
||||
let sourceModel = sourceSchema.rawModel()
|
||||
let destinationModel = destinationSchema.rawModel()
|
||||
|
||||
@@ -535,8 +552,12 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
// MARK: NSEntityMigrationPolicy
|
||||
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
|
||||
override func createDestinationInstances(
|
||||
forSource sInstance: NSManagedObject,
|
||||
in mapping: NSEntityMapping,
|
||||
manager: NSMigrationManager
|
||||
) throws(any Swift.Error) {
|
||||
|
||||
let userInfo = mapping.userInfo!
|
||||
let transformer = userInfo[CustomEntityMigrationPolicy.UserInfoKey.transformer]! as! CustomMapping.Transformer
|
||||
let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [KeyPathString: NSAttributeDescription]
|
||||
@@ -563,8 +584,12 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
|
||||
override func createRelationships(
|
||||
forDestination dInstance: NSManagedObject,
|
||||
in mapping: NSEntityMapping,
|
||||
manager: NSMigrationManager
|
||||
) throws(any Swift.Error) {
|
||||
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
@@ -583,8 +608,16 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
private let entityMappings: Set<CustomMapping>
|
||||
|
||||
private func resolveEntityMappings(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel) -> (delete: Set<CustomMapping>, insert: Set<CustomMapping>, copy: Set<CustomMapping>, transform: Set<CustomMapping>) {
|
||||
|
||||
private func resolveEntityMappings(
|
||||
sourceModel: NSManagedObjectModel,
|
||||
destinationModel: NSManagedObjectModel
|
||||
) -> (
|
||||
delete: Set<CustomMapping>,
|
||||
insert: Set<CustomMapping>,
|
||||
copy: Set<CustomMapping>,
|
||||
transform: Set<CustomMapping>
|
||||
) {
|
||||
|
||||
var deleteMappings: Set<CustomMapping> = []
|
||||
var insertMappings: Set<CustomMapping> = []
|
||||
var copyMappings: Set<CustomMapping> = []
|
||||
|
||||
375
Sources/DataStack+Concurrency.swift
Normal file
375
Sources/DataStack+Concurrency.swift
Normal file
@@ -0,0 +1,375 @@
|
||||
//
|
||||
// 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(any Swift.Error) -> T {
|
||||
|
||||
return try await Internals.withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.addStorage(
|
||||
storage,
|
||||
completion: {
|
||||
|
||||
continuation.resume(with: $0)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
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>, any 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(any Swift.Error) -> O? {
|
||||
|
||||
return try await Internals.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(any Swift.Error) -> O? {
|
||||
|
||||
return try await Internals.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(any Swift.Error) -> O? {
|
||||
|
||||
return try await Internals.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 @Sendable (
|
||||
_ mapping: [O.UniqueIDType: O.ImportSource]
|
||||
) throws(any Swift.Error) -> [O.UniqueIDType: O.ImportSource] = { $0 }
|
||||
) async throws(any Swift.Error) -> [O]
|
||||
where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
return try await Internals.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 @Sendable (AsynchronousDataTransaction) throws(any Swift.Error) -> Output
|
||||
) async throws(any Swift.Error) -> Output {
|
||||
|
||||
return try await Internals.withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.base.perform(
|
||||
asynchronous: asynchronous,
|
||||
completion: {
|
||||
|
||||
continuation.resume(with: $0)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,9 @@ extension DataStack {
|
||||
- parameter object: the `DynamicObject` to observe changes from
|
||||
- returns: an `ObjectPublisher` that broadcasts changes to `object`
|
||||
*/
|
||||
public func publishObject<O: DynamicObject>(_ object: O) -> ObjectPublisher<O> {
|
||||
public func publishObject<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> ObjectPublisher<O> {
|
||||
|
||||
return self.publishObject(object.cs_id())
|
||||
}
|
||||
@@ -50,7 +52,9 @@ extension DataStack {
|
||||
- parameter objectID: the `ObjectID` of the object to observe changes from
|
||||
- returns: an `ObjectPublisher` that broadcasts changes to `object`
|
||||
*/
|
||||
public func publishObject<O: DynamicObject>(_ objectID: O.ObjectID) -> ObjectPublisher<O> {
|
||||
public func publishObject<O: DynamicObject>(
|
||||
_ objectID: O.ObjectID
|
||||
) -> ObjectPublisher<O> {
|
||||
|
||||
let context = self.unsafeContext()
|
||||
return context.objectPublisher(objectID: objectID)
|
||||
@@ -74,7 +78,9 @@ extension DataStack {
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListPublisher` that broadcasts changes to the fetched results
|
||||
*/
|
||||
public func publishList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListPublisher<B.ObjectType> {
|
||||
public func publishList<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) -> ListPublisher<B.ObjectType> {
|
||||
|
||||
return self.publishList(
|
||||
clauseChain.from,
|
||||
@@ -101,7 +107,9 @@ extension DataStack {
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListPublisher` that broadcasts changes to the fetched results
|
||||
*/
|
||||
public func publishList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListPublisher<B.ObjectType> {
|
||||
public func publishList<B: SectionMonitorBuilderType>(
|
||||
_ clauseChain: B
|
||||
) -> ListPublisher<B.ObjectType> {
|
||||
|
||||
return self.publishList(
|
||||
clauseChain.from,
|
||||
@@ -117,7 +125,10 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListPublisher` that broadcasts changes to the fetched results
|
||||
*/
|
||||
public func publishList<O>(_ from: From<O>, _ fetchClauses: FetchClause...) -> ListPublisher<O> {
|
||||
public func publishList<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> ListPublisher<O> {
|
||||
|
||||
return self.publishList(from, fetchClauses)
|
||||
}
|
||||
@@ -129,7 +140,10 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListPublisher` that broadcasts changes to the fetched results
|
||||
*/
|
||||
public func publishList<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) -> ListPublisher<O> {
|
||||
public func publishList<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> ListPublisher<O> {
|
||||
|
||||
return ListPublisher(
|
||||
dataStack: self,
|
||||
@@ -155,7 +169,11 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListPublisher` that broadcasts changes to the fetched results
|
||||
*/
|
||||
public func publishList<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) -> ListPublisher<O> {
|
||||
public func publishList<O>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> ListPublisher<O> {
|
||||
|
||||
return self.publishList(
|
||||
from,
|
||||
@@ -172,7 +190,11 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListPublisher` that broadcasts changes to the fetched results
|
||||
*/
|
||||
public func publishList<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) -> ListPublisher<O> {
|
||||
public func publishList<O>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> ListPublisher<O> {
|
||||
|
||||
return ListPublisher(
|
||||
dataStack: self,
|
||||
@@ -189,51 +211,6 @@ extension DataStack {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "publishObject(_:)")
|
||||
public func objectPublisher<O: DynamicObject>(_ object: O) -> ObjectPublisher<O> {
|
||||
|
||||
return self.publishObject(object)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "publishList(_:_:)")
|
||||
public func listPublisher<O>(_ from: From<O>, _ fetchClauses: FetchClause...) -> ListPublisher<O> {
|
||||
|
||||
return self.publishList(from, fetchClauses)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "publishList(_:_:)")
|
||||
public func listPublisher<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) -> ListPublisher<O> {
|
||||
|
||||
return self.publishList(from, fetchClauses)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "publishList(_:)")
|
||||
public func listPublisher<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListPublisher<B.ObjectType> {
|
||||
|
||||
return self.publishList(clauseChain)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "publishList(_:_:_:)")
|
||||
public func listPublisher<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) -> ListPublisher<O> {
|
||||
|
||||
return self.publishList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "publishList(_:_:_:)")
|
||||
public func listPublisher<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) -> ListPublisher<O> {
|
||||
|
||||
return self.publishList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "publishList(_:)")
|
||||
public func listPublisher<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListPublisher<B.ObjectType> {
|
||||
|
||||
return self.publishList(clauseChain)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,8 +47,11 @@ extension DataStack {
|
||||
- parameter storage: the storage
|
||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` 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>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
|
||||
public func addStorage<T>(
|
||||
_ storage: T,
|
||||
completion: @escaping (SetupResult<T>) -> Void
|
||||
) {
|
||||
|
||||
self.coordinator.performAsynchronously {
|
||||
|
||||
if let _ = self.persistentStoreForStorage(storage) {
|
||||
@@ -105,8 +108,11 @@ extension DataStack {
|
||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` 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 `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
|
||||
*/
|
||||
public func addStorage<T: LocalStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) -> Progress? {
|
||||
|
||||
public func addStorage<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
completion: @escaping (SetupResult<T>) -> Void
|
||||
) -> Progress? {
|
||||
|
||||
let fileURL = storage.fileURL
|
||||
Internals.assert(
|
||||
fileURL.isFileURL,
|
||||
@@ -256,8 +262,11 @@ extension DataStack {
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: a `Progress` instance if a migration has started, or `nil` is no migrations are required
|
||||
*/
|
||||
public func upgradeStorageIfNeeded<T: LocalStorage>(_ storage: T, completion: @escaping (MigrationResult) -> Void) throws -> Progress? {
|
||||
|
||||
public func upgradeStorageIfNeeded<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
completion: @escaping (MigrationResult) -> Void
|
||||
) throws(CoreStoreError) -> Progress? {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
|
||||
let fileURL = storage.fileURL
|
||||
@@ -298,8 +307,10 @@ extension DataStack {
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: a `MigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, an error is thrown if either inspection of the store failed, or if no mapping model was found/inferred.
|
||||
*/
|
||||
public func requiredMigrationsForStorage<T: LocalStorage>(_ storage: T) throws -> [MigrationType] {
|
||||
|
||||
public func requiredMigrationsForStorage<T: LocalStorage>(
|
||||
_ storage: T
|
||||
) throws(CoreStoreError) -> [MigrationType] {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
|
||||
let fileURL = storage.fileURL
|
||||
@@ -362,8 +373,12 @@ extension DataStack {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func upgradeStorageIfNeeded<T: LocalStorage>(_ storage: T, metadata: [String: Any], completion: @escaping (MigrationResult) -> Void) -> Progress? {
|
||||
|
||||
private func upgradeStorageIfNeeded<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
metadata: [String: Any],
|
||||
completion: @escaping (MigrationResult) -> Void
|
||||
) -> Progress? {
|
||||
|
||||
guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata) else {
|
||||
|
||||
let error = CoreStoreError.mappingModelNotFound(
|
||||
@@ -485,35 +500,38 @@ extension DataStack {
|
||||
return progress
|
||||
}
|
||||
|
||||
private func computeMigrationFromStorage<T: LocalStorage>(_ storage: T, metadata: [String: Any]) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? {
|
||||
|
||||
private func computeMigrationFromStorage<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
metadata: [String: Any]
|
||||
) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? {
|
||||
|
||||
let schemaHistory = self.schemaHistory
|
||||
if schemaHistory.rawModel.isConfiguration(withName: storage.configuration, compatibleWithStoreMetadata: metadata) {
|
||||
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
guard let initialSchema = schemaHistory.schema(for: metadata) else {
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
var currentVersion = initialSchema.modelVersion
|
||||
let migrationChain: MigrationChain = schemaHistory.migrationChain.isEmpty
|
||||
? [currentVersion: schemaHistory.currentModelVersion]
|
||||
: schemaHistory.migrationChain
|
||||
|
||||
|
||||
var migrationSteps = [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]()
|
||||
|
||||
|
||||
while let nextVersion = migrationChain.nextVersionFrom(currentVersion),
|
||||
let sourceSchema = schemaHistory.schema(for: currentVersion),
|
||||
sourceSchema.modelVersion != schemaHistory.currentModelVersion,
|
||||
let destinationSchema = schemaHistory.schema(for: nextVersion) {
|
||||
|
||||
|
||||
let mappingProviders = storage.migrationMappingProviders
|
||||
do {
|
||||
|
||||
|
||||
try withExtendedLifetime((sourceSchema.rawModel(), destinationSchema.rawModel())) {
|
||||
|
||||
|
||||
let (sourceModel, destinationModel) = $0
|
||||
let mapping = try mappingProviders.findMapping(
|
||||
sourceSchema: sourceSchema,
|
||||
@@ -531,22 +549,29 @@ extension DataStack {
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
currentVersion = nextVersion
|
||||
}
|
||||
|
||||
|
||||
if migrationSteps.last?.destinationModel == schemaHistory.rawModel {
|
||||
|
||||
|
||||
return migrationSteps
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private func startMigrationForStorage<T: LocalStorage>(_ storage: T, sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType, progress: Progress) throws {
|
||||
|
||||
private func startMigrationForStorage<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
sourceModel: NSManagedObjectModel,
|
||||
destinationModel: NSManagedObjectModel,
|
||||
mappingModel: NSMappingModel,
|
||||
migrationType: MigrationType,
|
||||
progress: Progress
|
||||
) throws(CoreStoreError) {
|
||||
|
||||
do {
|
||||
|
||||
try storage.cs_finalizeStorageAndWait(soureModelHint: sourceModel)
|
||||
@@ -703,8 +728,12 @@ extension DataStack {
|
||||
|
||||
extension Array where Element == SchemaMappingProvider {
|
||||
|
||||
func findMapping(sourceSchema: DynamicSchema, destinationSchema: DynamicSchema, storage: LocalStorage) throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
|
||||
|
||||
func findMapping(
|
||||
sourceSchema: DynamicSchema,
|
||||
destinationSchema: DynamicSchema,
|
||||
storage: LocalStorage
|
||||
) throws(CoreStoreError) -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
|
||||
|
||||
for element in self {
|
||||
|
||||
switch element {
|
||||
|
||||
@@ -37,8 +37,10 @@ extension DataStack {
|
||||
- parameter object: the `DynamicObject` to observe changes from
|
||||
- returns: an `ObjectMonitor` that monitors changes to `object`
|
||||
*/
|
||||
public func monitorObject<O: DynamicObject>(_ object: O) -> ObjectMonitor<O> {
|
||||
|
||||
public func monitorObject<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> ObjectMonitor<O> {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -53,8 +55,11 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public func monitorList<O>(_ from: From<O>, _ fetchClauses: FetchClause...) -> ListMonitor<O> {
|
||||
|
||||
public func monitorList<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> ListMonitor<O> {
|
||||
|
||||
return self.monitorList(from, fetchClauses)
|
||||
}
|
||||
|
||||
@@ -65,8 +70,11 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public func monitorList<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) -> ListMonitor<O> {
|
||||
|
||||
public func monitorList<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> ListMonitor<O> {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -99,8 +107,10 @@ extension DataStack {
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
*/
|
||||
public func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
public func monitorList<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.monitorList(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
@@ -114,8 +124,12 @@ extension DataStack {
|
||||
- parameter from: a `From` clause indicating the entity type
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public func monitorList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
public func monitorList<O>(
|
||||
createAsynchronously: @escaping (ListMonitor<O>) -> Void,
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) {
|
||||
|
||||
self.monitorList(
|
||||
createAsynchronously: createAsynchronously,
|
||||
from,
|
||||
@@ -130,8 +144,12 @@ extension DataStack {
|
||||
- parameter from: a `From` clause indicating the entity type
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public func monitorList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
public func monitorList<O>(
|
||||
createAsynchronously: @escaping (ListMonitor<O>) -> Void,
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -169,8 +187,11 @@ extension DataStack {
|
||||
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
*/
|
||||
public func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
public func monitorList<B: FetchChainableBuilderType>(
|
||||
createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void,
|
||||
_ clauseChain: B
|
||||
) {
|
||||
|
||||
self.monitorList(
|
||||
createAsynchronously: createAsynchronously,
|
||||
clauseChain.from,
|
||||
@@ -186,8 +207,12 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public func monitorSectionedList<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) -> ListMonitor<O> {
|
||||
|
||||
public func monitorSectionedList<O>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> ListMonitor<O> {
|
||||
|
||||
return self.monitorSectionedList(
|
||||
from,
|
||||
sectionBy,
|
||||
@@ -203,8 +228,12 @@ extension DataStack {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public func monitorSectionedList<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) -> ListMonitor<O> {
|
||||
|
||||
public func monitorSectionedList<O>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> ListMonitor<O> {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -239,8 +268,10 @@ extension DataStack {
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(
|
||||
_ clauseChain: B
|
||||
) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.monitorSectionedList(
|
||||
clauseChain.from,
|
||||
clauseChain.sectionBy,
|
||||
@@ -256,8 +287,13 @@ extension DataStack {
|
||||
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public func monitorSectionedList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
public func monitorSectionedList<O>(
|
||||
createAsynchronously: @escaping (ListMonitor<O>) -> Void,
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) {
|
||||
|
||||
self.monitorSectionedList(
|
||||
createAsynchronously: createAsynchronously,
|
||||
from,
|
||||
@@ -274,8 +310,13 @@ extension DataStack {
|
||||
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public func monitorSectionedList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
public func monitorSectionedList<O>(
|
||||
createAsynchronously: @escaping (ListMonitor<O>) -> Void,
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -314,8 +355,11 @@ extension DataStack {
|
||||
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
*/
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(
|
||||
createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void,
|
||||
_ clauseChain: B
|
||||
) {
|
||||
|
||||
self.monitorSectionedList(
|
||||
createAsynchronously: createAsynchronously,
|
||||
clauseChain.from,
|
||||
|
||||
@@ -39,8 +39,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter object: a reference to the object created/fetched outside the `DataStack`
|
||||
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject>(_ object: O) -> O? {
|
||||
|
||||
public func fetchExisting<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> O? {
|
||||
|
||||
return self.mainContext.fetchExisting(object)
|
||||
}
|
||||
|
||||
@@ -50,8 +52,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject>(_ objectID: NSManagedObjectID) -> O? {
|
||||
|
||||
public func fetchExisting<O: DynamicObject>(
|
||||
_ objectID: NSManagedObjectID
|
||||
) -> O? {
|
||||
|
||||
return self.mainContext.fetchExisting(objectID)
|
||||
}
|
||||
|
||||
@@ -61,8 +65,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter objects: an array of `DynamicObject`s created/fetched outside the `DataStack`
|
||||
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objects: S) -> [O] where S.Iterator.Element == O {
|
||||
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objects: S
|
||||
) -> [O] where S.Iterator.Element == O {
|
||||
|
||||
return self.mainContext.fetchExisting(objects)
|
||||
}
|
||||
|
||||
@@ -72,8 +78,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objectIDs: S) -> [O] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objectIDs: S
|
||||
) -> [O] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
return self.mainContext.fetchExisting(objectIDs)
|
||||
}
|
||||
|
||||
@@ -85,8 +93,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> O? {
|
||||
|
||||
public func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -102,8 +113,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> O? {
|
||||
|
||||
public func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -124,8 +138,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> B.ObjectType? {
|
||||
|
||||
public func fetchOne<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ObjectType? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -141,8 +157,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [O] {
|
||||
|
||||
public func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -158,8 +177,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [O] {
|
||||
|
||||
public func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -180,7 +202,9 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [B.ObjectType] {
|
||||
public func fetchAll<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [B.ObjectType] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -197,8 +221,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> Int {
|
||||
|
||||
public func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -214,8 +241,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> Int {
|
||||
|
||||
public func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -236,8 +266,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
|
||||
|
||||
public func fetchCount<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -253,8 +285,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -270,8 +305,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -292,8 +330,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -309,8 +349,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -326,8 +369,11 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -348,8 +394,10 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -371,8 +419,12 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: QueryClause...) throws -> U? {
|
||||
|
||||
public func queryValue<O, U: QueryableAttributeType>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, U>,
|
||||
_ queryClauses: QueryClause...
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -391,8 +443,12 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: [QueryClause]) throws -> U? {
|
||||
|
||||
public func queryValue<O, U: QueryableAttributeType>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, U>,
|
||||
_ queryClauses: [QueryClause]
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -415,13 +471,19 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query as specified by the `QueryChainableBuilderType`, or `nil` if no match was found.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> B.ResultType? where B.ResultType: QueryableAttributeType {
|
||||
|
||||
public func queryValue<B: QueryChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ResultType? where B.ResultType: QueryableAttributeType {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
|
||||
)
|
||||
return try self.mainContext.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||
return try self.mainContext.queryValue(
|
||||
clauseChain.from,
|
||||
clauseChain.select,
|
||||
clauseChain.queryClauses
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,8 +497,12 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
|
||||
|
||||
public func queryAttributes<O>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, NSDictionary>,
|
||||
_ queryClauses: QueryClause...
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -455,8 +521,12 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
|
||||
|
||||
public func queryAttributes<O>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, NSDictionary>,
|
||||
_ queryClauses: [QueryClause]
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
|
||||
@@ -488,13 +558,19 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
public func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> [[String: Any]] where B.ResultType == NSDictionary {
|
||||
|
||||
public func queryAttributes<B: QueryChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [[String: Any]] where B.ResultType == NSDictionary {
|
||||
|
||||
Internals.assert(
|
||||
Thread.isMainThread,
|
||||
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
|
||||
)
|
||||
return try self.mainContext.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||
return try self.mainContext.queryAttributes(
|
||||
clauseChain.from,
|
||||
clauseChain.select,
|
||||
clauseChain.queryClauses
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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,10 +137,12 @@ 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> {
|
||||
|
||||
public func addStorage<T: LocalStorage>(
|
||||
_ storage: T
|
||||
) -> DataStack.AddStoragePublisher<T> {
|
||||
|
||||
return .init(
|
||||
dataStack: self.base,
|
||||
storage: storage
|
||||
@@ -315,7 +319,9 @@ extension DataStack.ReactiveNamespace {
|
||||
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 }
|
||||
preProcess: @escaping (
|
||||
_ mapping: [O.UniqueIDType: O.ImportSource]
|
||||
) throws(any Swift.Error) -> [O.UniqueIDType: O.ImportSource] = { $0 }
|
||||
) -> Future<[O], CoreStoreError> where S.Iterator.Element == O.ImportSource {
|
||||
|
||||
return .init { (promise) in
|
||||
@@ -365,7 +371,9 @@ extension DataStack.ReactiveNamespace {
|
||||
- returns: A `Future` whose event value be the value returned from the `task` closure.
|
||||
*/
|
||||
public func perform<Output>(
|
||||
_ asynchronous: @escaping (AsynchronousDataTransaction) throws -> Output
|
||||
_ asynchronous: @escaping (
|
||||
_ transaction: AsynchronousDataTransaction
|
||||
) throws(any Swift.Error) -> Output
|
||||
) -> Future<Output, CoreStoreError> {
|
||||
|
||||
return .init { (promise) in
|
||||
|
||||
@@ -39,7 +39,9 @@ extension DataStack {
|
||||
- parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
|
||||
*/
|
||||
public func perform<T>(
|
||||
asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T,
|
||||
asynchronous task: @escaping (
|
||||
_ transaction: AsynchronousDataTransaction
|
||||
) throws(any Swift.Error) -> T,
|
||||
sourceIdentifier: Any? = nil,
|
||||
completion: @escaping (AsynchronousDataTransaction.Result<T>) -> Void
|
||||
) {
|
||||
@@ -61,7 +63,9 @@ extension DataStack {
|
||||
- parameter failure: the closure executed if the save fails or if any errors are thrown within `task`. Cancelled `task`s will be indicated by `CoreStoreError.userCancelled`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
|
||||
*/
|
||||
public func perform<T>(
|
||||
asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T,
|
||||
asynchronous task: @escaping (
|
||||
_ transaction: AsynchronousDataTransaction
|
||||
) throws(any Swift.Error) -> T,
|
||||
sourceIdentifier: Any? = nil,
|
||||
success: @escaping (T) -> Void,
|
||||
failure: @escaping (CoreStoreError) -> Void
|
||||
@@ -117,41 +121,43 @@ extension DataStack {
|
||||
- returns: the value returned from `task`
|
||||
*/
|
||||
public func perform<T>(
|
||||
synchronous task: ((_ transaction: SynchronousDataTransaction) throws -> T),
|
||||
synchronous task: (
|
||||
_ transaction: SynchronousDataTransaction
|
||||
) throws(any Swift.Error) -> T,
|
||||
waitForAllObservers: Bool = true,
|
||||
sourceIdentifier: Any? = nil
|
||||
) throws -> T {
|
||||
|
||||
) throws(CoreStoreError) -> T {
|
||||
|
||||
let transaction = SynchronousDataTransaction(
|
||||
mainContext: self.rootSavingContext,
|
||||
queue: self.childTransactionQueue,
|
||||
sourceIdentifier: sourceIdentifier
|
||||
)
|
||||
return try transaction.transactionQueue.cs_sync {
|
||||
|
||||
return try transaction.transactionQueue.cs_sync { () throws(CoreStoreError) -> T in
|
||||
|
||||
defer {
|
||||
|
||||
|
||||
withExtendedLifetime((self, transaction), {})
|
||||
}
|
||||
let userInfo: T
|
||||
do {
|
||||
|
||||
|
||||
userInfo = try withoutActuallyEscaping(task, do: { try $0(transaction) })
|
||||
}
|
||||
catch let error as CoreStoreError {
|
||||
|
||||
throw error
|
||||
|
||||
throw error as CoreStoreError
|
||||
}
|
||||
catch let error {
|
||||
|
||||
|
||||
throw CoreStoreError.userError(error: error)
|
||||
}
|
||||
if case (_, let error?) = transaction.autoCommit(waitForMerge: waitForAllObservers) {
|
||||
|
||||
|
||||
throw error
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
return userInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,13 @@ 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 {
|
||||
|
||||
public func receive<S: Subscriber>(
|
||||
subscriber: S
|
||||
) where S.Input == Output, S.Failure == Failure {
|
||||
|
||||
subscriber.receive(
|
||||
subscription: AddStorageSubscription(
|
||||
dataStack: self.dataStack,
|
||||
@@ -63,56 +65,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
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -221,8 +241,8 @@ public final class DataStack: Equatable {
|
||||
- returns: the local SQLite storage added to the stack
|
||||
*/
|
||||
@discardableResult
|
||||
public func addStorageAndWait() throws -> SQLiteStore {
|
||||
|
||||
public func addStorageAndWait() throws(CoreStoreError) -> SQLiteStore {
|
||||
|
||||
return try self.addStorageAndWait(SQLiteStore())
|
||||
}
|
||||
|
||||
@@ -236,8 +256,10 @@ 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(CoreStoreError) -> T {
|
||||
|
||||
do {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
@@ -256,12 +278,11 @@ public final class DataStack: Equatable {
|
||||
}
|
||||
catch {
|
||||
|
||||
let storeError = CoreStoreError(error)
|
||||
Internals.log(
|
||||
storeError,
|
||||
error,
|
||||
"Failed to add \(Internals.typeName(storage)) to the stack."
|
||||
)
|
||||
throw storeError
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +296,10 @@ 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(CoreStoreError) -> T {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
|
||||
let fileURL = storage.fileURL
|
||||
@@ -374,7 +397,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 +466,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,57 +477,69 @@ 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(any Swift.Error) -> NSPersistentStore {
|
||||
|
||||
let persistentStore = try self.coordinator.addPersistentStore(
|
||||
ofType: type(of: storage).storeType,
|
||||
configurationName: storage.configuration,
|
||||
@@ -510,8 +547,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 +576,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]
|
||||
}
|
||||
|
||||
@@ -47,8 +47,14 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
public func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
public func log(
|
||||
level: LogLevel,
|
||||
message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
) {
|
||||
|
||||
#if DEBUG
|
||||
let icon: String
|
||||
let levelString: String
|
||||
@@ -83,8 +89,14 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
public func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
public func log(
|
||||
error: CoreStoreError,
|
||||
message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
) {
|
||||
|
||||
#if DEBUG
|
||||
Swift.print("⚠️ [CoreStore: Error] \((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n \(error)\n")
|
||||
#endif
|
||||
@@ -99,8 +111,14 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
public func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
public func assert(
|
||||
_ condition: @autoclosure () -> Bool,
|
||||
message: @autoclosure () -> String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
) {
|
||||
|
||||
#if DEBUG
|
||||
if condition() {
|
||||
|
||||
@@ -120,8 +138,13 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
public func abort(
|
||||
_ message: String,
|
||||
fileName: StaticString,
|
||||
lineNumber: Int,
|
||||
functionName: StaticString
|
||||
) {
|
||||
|
||||
Swift.print("❗ [CoreStore: Fatal Error] \((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n")
|
||||
Swift.fatalError(file: fileName, line: UInt(lineNumber))
|
||||
}
|
||||
|
||||
@@ -237,13 +237,4 @@ extension DiffableDataSource {
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
extension DiffableDataSource {
|
||||
|
||||
@available(*, deprecated, renamed: "CollectionViewAdapter")
|
||||
public typealias CollectionView = CollectionViewAdapter
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -240,13 +240,4 @@ extension DiffableDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
extension DiffableDataSource {
|
||||
|
||||
@available(*, deprecated, renamed: "CollectionViewAdapter")
|
||||
public typealias CollectionView = CollectionViewAdapter
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -299,13 +299,4 @@ extension DiffableDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
extension DiffableDataSource {
|
||||
|
||||
@available(*, deprecated, renamed: "TableViewAdapter")
|
||||
public typealias TableView = TableViewAdapter
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,8 +31,11 @@ import Foundation
|
||||
extension DispatchQueue {
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal static func serial(_ label: String, qos: DispatchQoS) -> DispatchQueue {
|
||||
|
||||
internal static func serial(
|
||||
_ label: String,
|
||||
qos: DispatchQoS
|
||||
) -> DispatchQueue {
|
||||
|
||||
return DispatchQueue(
|
||||
label: label,
|
||||
qos: qos,
|
||||
@@ -43,8 +46,11 @@ extension DispatchQueue {
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal static func concurrent(_ label: String, qos: DispatchQoS) -> DispatchQueue {
|
||||
|
||||
internal static func concurrent(
|
||||
_ label: String,
|
||||
qos: DispatchQoS
|
||||
) -> DispatchQueue {
|
||||
|
||||
return DispatchQueue(
|
||||
label: label,
|
||||
qos: qos,
|
||||
@@ -69,26 +75,57 @@ extension DispatchQueue {
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_sync<T>(_ closure: () throws -> T) rethrows -> T {
|
||||
|
||||
internal func cs_sync<T>(
|
||||
_ closure: () -> T
|
||||
) -> T {
|
||||
|
||||
return self.sync { autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_sync<T>(
|
||||
_ closure: () throws(any Swift.Error) -> T
|
||||
) throws(any Swift.Error) -> T {
|
||||
|
||||
return try self.sync { try autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_async(_ closure: @escaping () -> Void) {
|
||||
|
||||
internal func cs_sync<T>(
|
||||
_ closure: () throws(CoreStoreError) -> T
|
||||
) throws(CoreStoreError) -> T {
|
||||
|
||||
do {
|
||||
|
||||
return try self.sync { try autoreleasepool(invoking: closure) }
|
||||
}
|
||||
catch {
|
||||
|
||||
throw CoreStoreError(error)
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_async(
|
||||
_ closure: @escaping () -> Void
|
||||
) {
|
||||
|
||||
self.async { autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_barrierSync<T>(_ closure: () throws -> T) rethrows -> T {
|
||||
|
||||
internal func cs_barrierSync<T>(
|
||||
_ closure: () throws(any Swift.Error) -> T
|
||||
) rethrows -> T {
|
||||
|
||||
return try self.sync(flags: .barrier) { try autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_barrierAsync(_ closure: @escaping () -> Void) {
|
||||
|
||||
internal func cs_barrierAsync(
|
||||
_ closure: @escaping () -> Void
|
||||
) {
|
||||
|
||||
self.async(flags: .barrier) { autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
|
||||
@@ -42,23 +42,34 @@ public protocol DynamicObject: AnyObject {
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_forceCreate(entityDescription: NSEntityDescription, into context: NSManagedObjectContext, assignTo store: NSPersistentStore) -> Self
|
||||
|
||||
static func cs_forceCreate(
|
||||
entityDescription: NSEntityDescription,
|
||||
into context: NSManagedObjectContext,
|
||||
assignTo store: NSPersistentStore
|
||||
) -> Self
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_snapshotDictionary(id: ObjectID, context: NSManagedObjectContext) -> [String: Any]?
|
||||
|
||||
static func cs_snapshotDictionary(
|
||||
id: ObjectID,
|
||||
context: NSManagedObjectContext
|
||||
) -> [String: Any]?
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_fromRaw(object: NSManagedObject) -> Self
|
||||
|
||||
static func cs_fromRaw(
|
||||
object: NSManagedObject
|
||||
) -> Self
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_matches(object: NSManagedObject) -> Bool
|
||||
|
||||
static func cs_matches(
|
||||
object: NSManagedObject
|
||||
) -> Bool
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
@@ -88,8 +99,12 @@ extension NSManagedObject: DynamicObject {
|
||||
|
||||
// MARK: DynamicObject
|
||||
|
||||
public class func cs_forceCreate(entityDescription: NSEntityDescription, into context: NSManagedObjectContext, assignTo store: NSPersistentStore) -> Self {
|
||||
|
||||
public class func cs_forceCreate(
|
||||
entityDescription: NSEntityDescription,
|
||||
into context: NSManagedObjectContext,
|
||||
assignTo store: NSPersistentStore
|
||||
) -> Self {
|
||||
|
||||
let object = self.init(entity: entityDescription, insertInto: context)
|
||||
defer {
|
||||
|
||||
@@ -98,7 +113,10 @@ extension NSManagedObject: DynamicObject {
|
||||
return object
|
||||
}
|
||||
|
||||
public class func cs_snapshotDictionary(id: ObjectID, context: NSManagedObjectContext) -> [String: Any]? {
|
||||
public class func cs_snapshotDictionary(
|
||||
id: ObjectID,
|
||||
context: NSManagedObjectContext
|
||||
) -> [String: Any]? {
|
||||
|
||||
guard let object = context.fetchExisting(id) as NSManagedObject? else {
|
||||
|
||||
@@ -114,13 +132,21 @@ extension NSManagedObject: DynamicObject {
|
||||
}
|
||||
|
||||
public class func cs_fromRaw(object: NSManagedObject) -> Self {
|
||||
|
||||
|
||||
#if swift(>=5.9)
|
||||
return unsafeDowncast(object, to: self)
|
||||
|
||||
#else
|
||||
// unsafeDowncast fails debug assertion starting Swift 5.2
|
||||
return _unsafeUncheckedDowncast(object, to: self)
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
public static func cs_matches(object: NSManagedObject) -> Bool {
|
||||
|
||||
public static func cs_matches(
|
||||
object: NSManagedObject
|
||||
) -> Bool {
|
||||
|
||||
return object.isKind(of: self)
|
||||
}
|
||||
|
||||
@@ -142,8 +168,12 @@ extension CoreStoreObject {
|
||||
|
||||
// MARK: DynamicObject
|
||||
|
||||
public class func cs_forceCreate(entityDescription: NSEntityDescription, into context: NSManagedObjectContext, assignTo store: NSPersistentStore) -> Self {
|
||||
|
||||
public class 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 {
|
||||
@@ -153,12 +183,19 @@ extension CoreStoreObject {
|
||||
return self.cs_fromRaw(object: object)
|
||||
}
|
||||
|
||||
public class func cs_snapshotDictionary(id: ObjectID, context: NSManagedObjectContext) -> [String: Any]? {
|
||||
public class func cs_snapshotDictionary(
|
||||
id: ObjectID,
|
||||
context: NSManagedObjectContext
|
||||
) -> [String: Any]? {
|
||||
|
||||
var values: [KeyPathString: Any] = [:]
|
||||
if self.meta.needsReflection {
|
||||
|
||||
func initializeAttributes(mirror: Mirror, object: Self, into attributes: inout [KeyPathString: Any]) {
|
||||
func initializeAttributes(
|
||||
mirror: Mirror,
|
||||
object: Self,
|
||||
into attributes: inout [KeyPathString: Any]
|
||||
) {
|
||||
|
||||
if let superClassMirror = mirror.superclassMirror {
|
||||
|
||||
@@ -219,9 +256,9 @@ extension CoreStoreObject {
|
||||
let object = context.fetchExisting(id) as CoreStoreObject?,
|
||||
let rawObject = object.rawObject,
|
||||
!rawObject.isDeleted
|
||||
else {
|
||||
else {
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
for property in self.metaProperties(includeSuperclasses: true) {
|
||||
|
||||
@@ -261,8 +298,11 @@ extension CoreStoreObject {
|
||||
|
||||
return unsafeDowncast(coreStoreObject, to: self)
|
||||
}
|
||||
func forceTypeCast<T: CoreStoreObject>(_ type: AnyClass, to: T.Type) -> T.Type {
|
||||
|
||||
func forceTypeCast<T: CoreStoreObject>(
|
||||
_ type: AnyClass,
|
||||
to: T.Type
|
||||
) -> T.Type {
|
||||
|
||||
return type as! T.Type
|
||||
}
|
||||
let coreStoreObject = forceTypeCast(object.entity.dynamicObjectType!, to: self).init(rawObject: object)
|
||||
@@ -270,8 +310,10 @@ extension CoreStoreObject {
|
||||
return coreStoreObject
|
||||
}
|
||||
|
||||
public static func cs_matches(object: NSManagedObject) -> Bool {
|
||||
|
||||
public static func cs_matches(
|
||||
object: NSManagedObject
|
||||
) -> Bool {
|
||||
|
||||
guard let type = object.entity.coreStoreEntity?.type else {
|
||||
|
||||
return false
|
||||
|
||||
@@ -70,8 +70,14 @@ public final class Entity<O: CoreStoreObject>: DynamicEntity {
|
||||
- parameter indexes: the compound indexes for the entity as an array of arrays. The arrays contained in the returned array contain `KeyPath`s to properties of the entity.
|
||||
- parameter uniqueConstraints: sets uniqueness constraints for the entity. A uniqueness constraint is a set of one or more `KeyPath`s whose value must be unique over the set of instances of that entity. This value forms part of the entity's version hash. Uniqueness constraint violations can be computationally expensive to handle. It is highly suggested that there be only one uniqueness constraint per entity hierarchy. Uniqueness constraints must be defined at the highest level possible, and CoreStore will raise an assertion failure if unique constraints are added to a sub entity.
|
||||
*/
|
||||
public convenience init(_ entityName: String, isAbstract: Bool = false, versionHashModifier: String? = nil, indexes: [[PartialKeyPath<O>]] = [], uniqueConstraints: [[PartialKeyPath<O>]]) {
|
||||
|
||||
public convenience init(
|
||||
_ entityName: String,
|
||||
isAbstract: Bool = false,
|
||||
versionHashModifier: String? = nil,
|
||||
indexes: [[PartialKeyPath<O>]] = [],
|
||||
uniqueConstraints: [[PartialKeyPath<O>]]
|
||||
) {
|
||||
|
||||
self.init(
|
||||
O.self,
|
||||
entityName,
|
||||
@@ -92,7 +98,12 @@ public final class Entity<O: CoreStoreObject>: DynamicEntity {
|
||||
- parameter versionHashModifier: the version hash modifier for the entity. Used to mark or denote an entity as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where, for example, the structure of an entity is unchanged but the format or content of data has changed.)
|
||||
- parameter indexes: the compound indexes for the entity as an array of arrays. The arrays contained in the returned array contain `KeyPath`s to properties of the entity.
|
||||
*/
|
||||
public convenience init(_ entityName: String, isAbstract: Bool = false, versionHashModifier: String? = nil, indexes: [[PartialKeyPath<O>]] = []) {
|
||||
public convenience init(
|
||||
_ entityName: String,
|
||||
isAbstract: Bool = false,
|
||||
versionHashModifier: String? = nil,
|
||||
indexes: [[PartialKeyPath<O>]] = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
O.self,
|
||||
@@ -115,8 +126,15 @@ public final class Entity<O: CoreStoreObject>: DynamicEntity {
|
||||
- parameter indexes: the compound indexes for the entity as an array of arrays. The arrays contained in the returned array contain KeyPath's to properties of the entity.
|
||||
- parameter uniqueConstraints: sets uniqueness constraints for the entity. A uniqueness constraint is a set of one or more `KeyPath`s whose value must be unique over the set of instances of that entity. This value forms part of the entity's version hash. Uniqueness constraint violations can be computationally expensive to handle. It is highly suggested that there be only one uniqueness constraint per entity hierarchy. Uniqueness constraints must be defined at the highest level possible, and CoreStore will raise an assertion failure if unique constraints are added to a sub entity.
|
||||
*/
|
||||
public init(_ type: O.Type, _ entityName: String, isAbstract: Bool = false, versionHashModifier: String? = nil, indexes: [[PartialKeyPath<O>]] = [], uniqueConstraints: [[PartialKeyPath<O>]]) {
|
||||
|
||||
public init(
|
||||
_ type: O.Type,
|
||||
_ entityName: String,
|
||||
isAbstract: Bool = false,
|
||||
versionHashModifier: String? = nil,
|
||||
indexes: [[PartialKeyPath<O>]] = [],
|
||||
uniqueConstraints: [[PartialKeyPath<O>]]
|
||||
) {
|
||||
|
||||
let meta = O.meta
|
||||
let toStringArray: ([PartialKeyPath<O>]) -> [KeyPathString] = {
|
||||
|
||||
@@ -147,7 +165,13 @@ public final class Entity<O: CoreStoreObject>: DynamicEntity {
|
||||
- parameter indexes: the compound indexes for the entity as an array of arrays. The arrays contained in the returned array contain KeyPath's to properties of the entity.
|
||||
- parameter uniqueConstraints: sets uniqueness constraints for the entity. A uniqueness constraint is a set of one or more `KeyPath`s whose value must be unique over the set of instances of that entity. This value forms part of the entity's version hash. Uniqueness constraint violations can be computationally expensive to handle. It is highly suggested that there be only one uniqueness constraint per entity hierarchy. Uniqueness constraints must be defined at the highest level possible, and CoreStore will raise an assertion failure if unique constraints are added to a sub entity.
|
||||
*/
|
||||
public init(_ type: O.Type, _ entityName: String, isAbstract: Bool = false, versionHashModifier: String? = nil, indexes: [[PartialKeyPath<O>]] = []) {
|
||||
public init(
|
||||
_ type: O.Type,
|
||||
_ entityName: String,
|
||||
isAbstract: Bool = false,
|
||||
versionHashModifier: String? = nil,
|
||||
indexes: [[PartialKeyPath<O>]] = []
|
||||
) {
|
||||
|
||||
let meta = O.meta
|
||||
let toStringArray: ([PartialKeyPath<O>]) -> [KeyPathString] = {
|
||||
@@ -232,8 +256,15 @@ public /*abstract*/ class DynamicEntity: Hashable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(type: DynamicObject.Type, entityName: String, isAbstract: Bool, versionHashModifier: String?, indexes: [[KeyPathString]], uniqueConstraints: [[KeyPathString]]) {
|
||||
|
||||
internal init(
|
||||
type: DynamicObject.Type,
|
||||
entityName: String,
|
||||
isAbstract: Bool,
|
||||
versionHashModifier: String?,
|
||||
indexes: [[KeyPathString]],
|
||||
uniqueConstraints: [[KeyPathString]]
|
||||
) {
|
||||
|
||||
self.type = type
|
||||
self.entityName = entityName
|
||||
self.isAbstract = isAbstract
|
||||
|
||||
@@ -57,27 +57,38 @@ public protocol FieldRelationshipType {
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_toReturnType(from value: NativeValueType?) -> Self
|
||||
static func cs_toReturnType(
|
||||
from value: NativeValueType?
|
||||
) -> Self
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_toPublishedType(from value: SnapshotValueType, in context: NSManagedObjectContext) -> PublishedType
|
||||
static func cs_toPublishedType(
|
||||
from value: SnapshotValueType,
|
||||
in context: NSManagedObjectContext
|
||||
) -> PublishedType
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_toNativeType(from value: Self) -> NativeValueType?
|
||||
static func cs_toNativeType(
|
||||
from value: Self
|
||||
) -> NativeValueType?
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_toSnapshotType(from value: PublishedType) -> SnapshotValueType
|
||||
static func cs_toSnapshotType(
|
||||
from value: PublishedType
|
||||
) -> SnapshotValueType
|
||||
|
||||
/**
|
||||
Used internally by CoreStore. Do not call directly.
|
||||
*/
|
||||
static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType
|
||||
static func cs_valueForSnapshot(
|
||||
from objectIDs: [DestinationObjectType.ObjectID]
|
||||
) -> SnapshotValueType
|
||||
}
|
||||
|
||||
|
||||
@@ -115,27 +126,38 @@ extension Optional: FieldRelationshipType, FieldRelationshipToOneType where Wrap
|
||||
|
||||
public typealias PublishedType = ObjectPublisher<DestinationObjectType>?
|
||||
|
||||
public static func cs_toReturnType(from value: NativeValueType?) -> Self {
|
||||
public static func cs_toReturnType(
|
||||
from value: NativeValueType?
|
||||
) -> Self {
|
||||
|
||||
return value.map(Wrapped.cs_fromRaw(object:))
|
||||
}
|
||||
|
||||
public static func cs_toPublishedType(from value: SnapshotValueType, in context: NSManagedObjectContext) -> PublishedType {
|
||||
public static func cs_toPublishedType(
|
||||
from value: SnapshotValueType,
|
||||
in context: NSManagedObjectContext
|
||||
) -> PublishedType {
|
||||
|
||||
return value.map(context.objectPublisher(objectID:))
|
||||
}
|
||||
|
||||
public static func cs_toNativeType(from value: Self) -> NativeValueType? {
|
||||
public static func cs_toNativeType(
|
||||
from value: Self
|
||||
) -> NativeValueType? {
|
||||
|
||||
return value?.cs_toRaw()
|
||||
}
|
||||
|
||||
public static func cs_toSnapshotType(from value: PublishedType) -> SnapshotValueType {
|
||||
public static func cs_toSnapshotType(
|
||||
from value: PublishedType
|
||||
) -> SnapshotValueType {
|
||||
|
||||
return value?.objectID()
|
||||
}
|
||||
|
||||
public static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType {
|
||||
public static func cs_valueForSnapshot(
|
||||
from objectIDs: [DestinationObjectType.ObjectID]
|
||||
) -> SnapshotValueType {
|
||||
|
||||
return objectIDs.first
|
||||
}
|
||||
@@ -156,7 +178,9 @@ extension Array: FieldRelationshipType, FieldRelationshipToManyType, FieldRelati
|
||||
|
||||
public typealias PublishedType = [ObjectPublisher<DestinationObjectType>]
|
||||
|
||||
public static func cs_toReturnType(from value: NativeValueType?) -> Self {
|
||||
public static func cs_toReturnType(
|
||||
from value: NativeValueType?
|
||||
) -> Self {
|
||||
|
||||
guard let value = value else {
|
||||
|
||||
@@ -165,22 +189,31 @@ extension Array: FieldRelationshipType, FieldRelationshipToManyType, FieldRelati
|
||||
return value.map({ Element.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
}
|
||||
|
||||
public static func cs_toPublishedType(from value: SnapshotValueType, in context: NSManagedObjectContext) -> PublishedType {
|
||||
public static func cs_toPublishedType(
|
||||
from value: SnapshotValueType,
|
||||
in context: NSManagedObjectContext
|
||||
) -> PublishedType {
|
||||
|
||||
return value.map(context.objectPublisher(objectID:))
|
||||
}
|
||||
|
||||
public static func cs_toNativeType(from value: Self) -> NativeValueType? {
|
||||
public static func cs_toNativeType(
|
||||
from value: Self
|
||||
) -> NativeValueType? {
|
||||
|
||||
return NSOrderedSet(array: value.map({ $0.rawObject! }))
|
||||
}
|
||||
|
||||
public static func cs_toSnapshotType(from value: PublishedType) -> SnapshotValueType {
|
||||
public static func cs_toSnapshotType(
|
||||
from value: PublishedType
|
||||
) -> SnapshotValueType {
|
||||
|
||||
return value.map({ $0.objectID() })
|
||||
}
|
||||
|
||||
public static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType {
|
||||
public static func cs_valueForSnapshot(
|
||||
from objectIDs: [DestinationObjectType.ObjectID]
|
||||
) -> SnapshotValueType {
|
||||
|
||||
return objectIDs
|
||||
}
|
||||
@@ -201,7 +234,9 @@ extension Set: FieldRelationshipType, FieldRelationshipToManyType, FieldRelation
|
||||
|
||||
public typealias PublishedType = Set<ObjectPublisher<DestinationObjectType>>
|
||||
|
||||
public static func cs_toReturnType(from value: NativeValueType?) -> Self {
|
||||
public static func cs_toReturnType(
|
||||
from value: NativeValueType?
|
||||
) -> Self {
|
||||
|
||||
guard let value = value else {
|
||||
|
||||
@@ -210,22 +245,31 @@ extension Set: FieldRelationshipType, FieldRelationshipToManyType, FieldRelation
|
||||
return Set(value.map({ Element.cs_fromRaw(object: $0 as! NSManagedObject) }))
|
||||
}
|
||||
|
||||
public static func cs_toPublishedType(from value: SnapshotValueType, in context: NSManagedObjectContext) -> PublishedType {
|
||||
public static func cs_toPublishedType(
|
||||
from value: SnapshotValueType,
|
||||
in context: NSManagedObjectContext
|
||||
) -> PublishedType {
|
||||
|
||||
return PublishedType(value.map(context.objectPublisher(objectID:)))
|
||||
}
|
||||
|
||||
public static func cs_toNativeType(from value: Self) -> NativeValueType? {
|
||||
public static func cs_toNativeType(
|
||||
from value: Self
|
||||
) -> NativeValueType? {
|
||||
|
||||
return NSSet(array: value.map({ $0.rawObject! }))
|
||||
}
|
||||
|
||||
public static func cs_toSnapshotType(from value: PublishedType) -> SnapshotValueType {
|
||||
public static func cs_toSnapshotType(
|
||||
from value: PublishedType
|
||||
) -> SnapshotValueType {
|
||||
|
||||
return SnapshotValueType(value.map({ $0.objectID() }))
|
||||
}
|
||||
|
||||
public static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType {
|
||||
public static func cs_valueForSnapshot(
|
||||
from objectIDs: [DestinationObjectType.ObjectID]
|
||||
) -> SnapshotValueType {
|
||||
|
||||
return .init(objectIDs)
|
||||
}
|
||||
|
||||
@@ -47,12 +47,6 @@ public struct FetchChainBuilder<O: DynamicObject>: FetchChainableBuilderType {
|
||||
|
||||
public var from: From<O>
|
||||
public var fetchClauses: [FetchClause] = []
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,23 +40,29 @@ public protocol FetchableSource: AnyObject {
|
||||
- parameter object: a reference to the object created/fetched outside the `FetchableSource`'s context
|
||||
- returns: the `DynamicObject` instance if the object exists in the `FetchableSource`'s context, or `nil` if not found.
|
||||
*/
|
||||
func fetchExisting<O: DynamicObject>(_ object: O) -> O?
|
||||
|
||||
func fetchExisting<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> O?
|
||||
|
||||
/**
|
||||
Fetches the `DynamicObject` instance in the `FetchableSource`'s context from an `NSManagedObjectID`.
|
||||
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `DynamicObject` instance if the object exists in the `FetchableSource`, or `nil` if not found.
|
||||
*/
|
||||
func fetchExisting<O: DynamicObject>(_ objectID: NSManagedObjectID) -> O?
|
||||
|
||||
func fetchExisting<O: DynamicObject>(
|
||||
_ objectID: NSManagedObjectID
|
||||
) -> O?
|
||||
|
||||
/**
|
||||
Fetches the `DynamicObject` instances in the `FetchableSource`'s context from references created from another managed object context.
|
||||
|
||||
- parameter objects: an array of `DynamicObject`s created/fetched outside the `FetchableSource`'s context
|
||||
- returns: the `DynamicObject` array for objects that exists in the `FetchableSource`
|
||||
*/
|
||||
func fetchExisting<O: DynamicObject, S: Sequence>(_ objects: S) -> [O] where S.Iterator.Element == O
|
||||
func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objects: S
|
||||
) -> [O] where S.Iterator.Element == O
|
||||
|
||||
/**
|
||||
Fetches the `DynamicObject` instances in the `FetchableSource`'s context from a list of `NSManagedObjectID`.
|
||||
@@ -64,7 +70,9 @@ public protocol FetchableSource: AnyObject {
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `DynamicObject` array for objects that exists in the `FetchableSource`'s context
|
||||
*/
|
||||
func fetchExisting<O: DynamicObject, S: Sequence>(_ objectIDs: S) -> [O] where S.Iterator.Element == NSManagedObjectID
|
||||
func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objectIDs: S
|
||||
) -> [O] where S.Iterator.Element == NSManagedObjectID
|
||||
|
||||
/**
|
||||
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -74,7 +82,10 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchOne<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> O?
|
||||
func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> O?
|
||||
|
||||
/**
|
||||
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -84,8 +95,11 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchOne<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> O?
|
||||
|
||||
func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> O?
|
||||
|
||||
/**
|
||||
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
@@ -99,7 +113,9 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> B.ObjectType?
|
||||
func fetchOne<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ObjectType?
|
||||
|
||||
/**
|
||||
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -109,7 +125,10 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchAll<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [O]
|
||||
func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [O]
|
||||
|
||||
/**
|
||||
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -119,8 +138,11 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchAll<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [O]
|
||||
|
||||
func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [O]
|
||||
|
||||
/**
|
||||
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
@@ -134,7 +156,9 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [B.ObjectType]
|
||||
func fetchAll<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [B.ObjectType]
|
||||
|
||||
/**
|
||||
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -144,7 +168,10 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchCount<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> Int
|
||||
func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> Int
|
||||
|
||||
/**
|
||||
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -154,8 +181,11 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchCount<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> Int
|
||||
|
||||
func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> Int
|
||||
|
||||
/**
|
||||
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
@@ -169,7 +199,9 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int
|
||||
func fetchCount<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> Int
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -179,7 +211,10 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID?
|
||||
func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> NSManagedObjectID?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -189,8 +224,11 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID?
|
||||
|
||||
func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> NSManagedObjectID?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
@@ -204,7 +242,9 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`, or `nil` if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> NSManagedObjectID?
|
||||
func fetchObjectID<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> NSManagedObjectID?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -214,7 +254,10 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID]
|
||||
func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID]
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -224,8 +267,11 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID]
|
||||
|
||||
func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID]
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
@@ -239,8 +285,10 @@ public protocol FetchableSource: AnyObject {
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`, or an empty array if no match was found
|
||||
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
|
||||
*/
|
||||
func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [NSManagedObjectID]
|
||||
|
||||
func fetchObjectIDs<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID]
|
||||
|
||||
/**
|
||||
The internal `NSManagedObjectContext` managed by this `FetchableSource`. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,8 @@ extension FieldContainer {
|
||||
@propertyWrapper
|
||||
public struct Coded<V>: AttributeKeyPathStringConvertible, FieldAttributeProtocol {
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -99,6 +101,63 @@ extension FieldContainer {
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
#else
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Coded("eyeColor", coder: FieldCoders.NSCoding.self)
|
||||
var eyeColor: UIColor = .black
|
||||
}
|
||||
```
|
||||
- Important: Any changes in the `coder` are not reflected in the VersionLock, so make sure that the encoder and decoder logic is compatible for all versions of your persistent store.
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter coder: The `FieldCoderType` to be used for encoding and decoding the value
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init<Coder: FieldCoderType>(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder fieldCoderType: Coder.Type,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) where Coder.FieldStoredValue == V {
|
||||
|
||||
self.init(
|
||||
defaultValue: initial,
|
||||
keyPath: keyPath,
|
||||
isOptional: false,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
valueTransformer: { Internals.AnyFieldCoder(fieldCoderType) },
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
@@ -124,8 +183,19 @@ extension FieldContainer {
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder fieldCoderType: Coder.Type,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) where Coder.FieldStoredValue == V {
|
||||
@@ -144,6 +214,8 @@ extension FieldContainer {
|
||||
)
|
||||
}
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -194,6 +266,74 @@ extension FieldContainer {
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Coded(
|
||||
"bloodType",
|
||||
coder: {
|
||||
encode: { $0.toData() },
|
||||
decode: { BloodType(fromData: $0) }
|
||||
}
|
||||
)
|
||||
var bloodType: BloodType = .unknown
|
||||
}
|
||||
```
|
||||
- Important: Any changes in the encoder/decoder are not reflected in the VersionLock, so make sure that the encoder and decoder logic is compatible for all versions of your persistent store.
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter coder: The closures to be used for encoding and decoding the value
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder: (
|
||||
encode: (V) -> Data?,
|
||||
decode: (Data?) -> V
|
||||
),
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
defaultValue: initial,
|
||||
keyPath: keyPath,
|
||||
isOptional: false,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) },
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -224,9 +364,23 @@ extension FieldContainer {
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder: (encode: (V) -> Data?, decode: (Data?) -> V),
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
coder: (
|
||||
encode: (V) -> Data?,
|
||||
decode: (Data?) -> V
|
||||
),
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) {
|
||||
@@ -324,7 +478,10 @@ extension FieldContainer {
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
internal static func read(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject
|
||||
) -> Any? {
|
||||
|
||||
let field = field as! Self
|
||||
if let customGetter = field.customGetter {
|
||||
@@ -345,7 +502,11 @@ extension FieldContainer {
|
||||
}
|
||||
}
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
internal static func modify(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject,
|
||||
newValue: Any?
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
@@ -460,10 +621,22 @@ extension FieldContainer {
|
||||
versionHashModifier: @escaping () -> String?,
|
||||
renamingIdentifier: @escaping () -> String?,
|
||||
valueTransformer: @escaping () -> Internals.AnyFieldCoder?,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? ,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)?,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? ,
|
||||
dynamicInitialValue: (() -> V)?,
|
||||
affectedByKeyPaths: @escaping () -> Set<KeyPathString>) {
|
||||
affectedByKeyPaths: @escaping () -> Set<KeyPathString>
|
||||
) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.entityDescriptionValues = {
|
||||
@@ -505,6 +678,8 @@ extension FieldContainer {
|
||||
|
||||
extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -548,6 +723,65 @@ extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Coded("eyeColor", coder: FieldCoders.NSCoding.self)
|
||||
var eyeColor: UIColor? = nil
|
||||
}
|
||||
```
|
||||
- Important: Any changes in the `coder` are not reflected in the VersionLock, so make sure that the encoder and decoder logic is compatible for all versions of your persistent store.
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter coder: The `FieldCoderType` to be used for encoding and decoding the value
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init<Coder: FieldCoderType>(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V = nil,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder: Coder.Type,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) where Coder.FieldStoredValue == V.Wrapped {
|
||||
|
||||
self.init(
|
||||
defaultValue: { initial().cs_wrappedValue },
|
||||
keyPath: keyPath,
|
||||
isOptional: true,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
valueTransformer: { Internals.AnyFieldCoder(coder) },
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
@@ -573,8 +807,19 @@ extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder: Coder.Type,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) where Coder.FieldStoredValue == V.Wrapped {
|
||||
@@ -593,6 +838,9 @@ extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -643,6 +891,74 @@ extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Coded(
|
||||
"bloodType",
|
||||
coder: {
|
||||
encode: { $0.toData() },
|
||||
decode: { BloodType(fromData: $0) }
|
||||
}
|
||||
)
|
||||
var bloodType: BloodType?
|
||||
}
|
||||
```
|
||||
- Important: Any changes in the encoder/decoder are not reflected in the VersionLock, so make sure that the encoder and decoder logic is compatible for all versions of your persistent store.
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter coder: The closures to be used for encoding and decoding the value
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V = nil,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder: (
|
||||
encode: (V) -> Data?,
|
||||
decode: (Data?) -> V
|
||||
),
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
defaultValue: { initial().cs_wrappedValue },
|
||||
keyPath: keyPath,
|
||||
isOptional: true,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) },
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -673,9 +989,23 @@ extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
coder: (encode: (V) -> Data?, decode: (Data?) -> V),
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
coder: (
|
||||
encode: (V) -> Data?,
|
||||
decode: (Data?) -> V
|
||||
),
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) {
|
||||
@@ -700,6 +1030,8 @@ extension FieldContainer.Coded where V: FieldOptionalType {
|
||||
|
||||
extension FieldContainer.Coded where V: DefaultNSSecureCodable {
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property. This overload is for types supported by Core Data's default NSSecureCodable implementation: `NSArray`, `NSDictionary`, `NSSet`, `NSString`, `NSNumber`, `NSDate`, `NSData`, `NSURL`, `NSUUID`, and `NSNull`.
|
||||
```
|
||||
@@ -740,6 +1072,62 @@ extension FieldContainer.Coded where V: DefaultNSSecureCodable {
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property. This overload is for types supported by Core Data's default NSSecureCodable implementation: `NSArray`, `NSDictionary`, `NSSet`, `NSString`, `NSNumber`, `NSDate`, `NSData`, `NSURL`, `NSUUID`, and `NSNull`.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Coded("customInfo")
|
||||
var customInfo: NSDictionary = [:]
|
||||
}
|
||||
```
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
defaultValue: initial,
|
||||
keyPath: keyPath,
|
||||
isOptional: false,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V>.self) },
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property. This overload is for types supported by Core Data's default NSSecureCodable implementation: `NSArray`, `NSDictionary`, `NSSet`, `NSString`, `NSNumber`, `NSDate`, `NSData`, `NSURL`, `NSUUID`, and `NSNull`.
|
||||
@@ -762,8 +1150,19 @@ extension FieldContainer.Coded where V: DefaultNSSecureCodable {
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) {
|
||||
@@ -788,6 +1187,8 @@ extension FieldContainer.Coded where V: DefaultNSSecureCodable {
|
||||
|
||||
extension FieldContainer.Coded where V: FieldOptionalType, V.Wrapped: DefaultNSSecureCodable {
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property. This overload is for types supported by Core Data's default NSSecureCodable implementation: `NSArray`, `NSDictionary`, `NSSet`, `NSString`, `NSNumber`, `NSDate`, `NSData`, `NSURL`, `NSUUID`, and `NSNull`.
|
||||
```
|
||||
@@ -828,6 +1229,62 @@ extension FieldContainer.Coded where V: FieldOptionalType, V.Wrapped: DefaultNSS
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property. This overload is for types supported by Core Data's default NSSecureCodable implementation: `NSArray`, `NSDictionary`, `NSSet`, `NSString`, `NSNumber`, `NSDate`, `NSData`, `NSURL`, `NSUUID`, and `NSNull`.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Coded("customInfo")
|
||||
var customInfo: NSDictionary? = nil
|
||||
}
|
||||
```
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V = nil,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
defaultValue: { initial().cs_wrappedValue },
|
||||
keyPath: keyPath,
|
||||
isOptional: true,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V.Wrapped>.self) },
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property. This overload is for types supported by Core Data's default NSSecureCodable implementation: `NSArray`, `NSDictionary`, `NSSet`, `NSString`, `NSNumber`, `NSDate`, `NSData`, `NSURL`, `NSUUID`, and `NSNull`.
|
||||
@@ -850,8 +1307,19 @@ extension FieldContainer.Coded where V: FieldOptionalType, V.Wrapped: DefaultNSS
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) {
|
||||
|
||||
@@ -167,7 +167,10 @@ extension FieldContainer {
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
internal static func read(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject
|
||||
) -> Any? {
|
||||
|
||||
let field = field as! Self
|
||||
let keyPath = field.keyPath
|
||||
@@ -176,8 +179,12 @@ extension FieldContainer {
|
||||
)
|
||||
}
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
|
||||
internal static func modify(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject,
|
||||
newValue: Any?
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
"Attempted to update a \(Internals.typeName(O.self))'s value from outside a transaction."
|
||||
@@ -196,7 +203,10 @@ extension FieldContainer {
|
||||
|
||||
internal let entityDescriptionValues: () -> FieldRelationshipProtocol.EntityDescriptionValues
|
||||
|
||||
internal static func valueForSnapshot(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
internal static func valueForSnapshot(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject
|
||||
) -> Any? {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
|
||||
@@ -50,6 +50,8 @@ extension FieldContainer {
|
||||
@propertyWrapper
|
||||
public struct Stored<V: FieldStorableType>: AttributeKeyPathStringConvertible, FieldAttributeProtocol {
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -89,6 +91,61 @@ extension FieldContainer {
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Stored("title")
|
||||
var title: String = "Mr."
|
||||
}
|
||||
```
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
wrappedValue: initial,
|
||||
keyPath: keyPath,
|
||||
isOptional: false,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
@@ -111,8 +168,19 @@ extension FieldContainer {
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
|
||||
dynamicInitialValue: @escaping () -> V
|
||||
) {
|
||||
@@ -209,7 +277,10 @@ extension FieldContainer {
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
internal static func read(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject
|
||||
) -> Any? {
|
||||
|
||||
let field = field as! Self
|
||||
if let customGetter = field.customGetter {
|
||||
@@ -230,7 +301,10 @@ extension FieldContainer {
|
||||
}
|
||||
}
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
internal static func modify(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject, newValue: Any?
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
@@ -333,7 +407,8 @@ extension FieldContainer {
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)?,
|
||||
dynamicInitialValue: (() -> V)?,
|
||||
affectedByKeyPaths: @escaping () -> Set<KeyPathString>) {
|
||||
affectedByKeyPaths: @escaping () -> Set<KeyPathString>
|
||||
) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.entityDescriptionValues = {
|
||||
@@ -357,8 +432,19 @@ extension FieldContainer {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?
|
||||
private let customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)?
|
||||
private let customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)?
|
||||
private let customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)?
|
||||
private let dynamicInitialValue: (() -> V)?
|
||||
}
|
||||
}
|
||||
@@ -368,6 +454,8 @@ extension FieldContainer {
|
||||
|
||||
extension FieldContainer.Stored where V: FieldOptionalType {
|
||||
|
||||
#if swift(<5.4)
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
@@ -407,6 +495,50 @@ extension FieldContainer.Stored where V: FieldOptionalType {
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
```
|
||||
class Person: CoreStoreObject {
|
||||
|
||||
@Field.Stored("nickname")
|
||||
var nickname: String?
|
||||
}
|
||||
```
|
||||
- parameter initial: the initial value for the property that is shared for all instances of this object. Note that this is evaluated during `DataStack` setup, not during object creation. To assign a value during object creation, use the `dynamicInitialValue` argument instead.
|
||||
- parameter keyPath: the permanent attribute name for this property.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the properties are unchanged but the format or content of its data are changed.)
|
||||
- parameter previousVersionKeyPath: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property's `keyPath` with a matching destination entity property's `previousVersionKeyPath` indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's `keyPath`.
|
||||
- parameter customGetter: use this closure as an "override" for the default property getter. The closure receives a `ObjectProxy<O>`, which acts as a type-safe proxy for the receiver. When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively. Do not make assumptions on the thread/queue that the closure is executed on; accessors may be called from `NSError` logs for example.
|
||||
- parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `ObjectProxy<O>`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `ObjectProxy<O>`, make sure to use `field.primitiveValue` instead of `field.value`, which would unintentionally execute the same closure again recursively.
|
||||
- parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`.
|
||||
*/
|
||||
public init(
|
||||
wrappedValue initial: @autoclosure @escaping () -> V = nil,
|
||||
_ keyPath: KeyPathString = { fatalError("'keyPath' argument required (SR-13069 workaround)") }(),
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
|
||||
) {
|
||||
|
||||
self.init(
|
||||
wrappedValue: initial,
|
||||
keyPath: keyPath,
|
||||
isOptional: true,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: previousVersionKeyPath,
|
||||
customGetter: customGetter,
|
||||
customSetter: customSetter,
|
||||
dynamicInitialValue: nil,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initializes the metadata for the property.
|
||||
|
||||
@@ -80,7 +80,13 @@ extension FieldContainer {
|
||||
public init(
|
||||
_ keyPath: KeyPathString,
|
||||
customGetter: @escaping (_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []) {
|
||||
|
||||
self.init(
|
||||
@@ -99,8 +105,19 @@ extension FieldContainer {
|
||||
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||
_ keyPath: KeyPathString,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []) {
|
||||
|
||||
fatalError()
|
||||
@@ -185,7 +202,10 @@ extension FieldContainer {
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
internal static func read(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject
|
||||
) -> Any? {
|
||||
|
||||
let field = field as! Self
|
||||
if let customGetter = field.customGetter {
|
||||
@@ -206,7 +226,11 @@ extension FieldContainer {
|
||||
}
|
||||
}
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
internal static func modify(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject,
|
||||
newValue: Any?
|
||||
) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
@@ -285,7 +309,8 @@ extension FieldContainer {
|
||||
keyPath: KeyPathString,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? ,
|
||||
affectedByKeyPaths: @escaping () -> Set<KeyPathString>) {
|
||||
affectedByKeyPaths: @escaping () -> Set<KeyPathString>
|
||||
) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.entityDescriptionValues = {
|
||||
@@ -308,8 +333,19 @@ extension FieldContainer {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?
|
||||
private let customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)?
|
||||
private let customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)?
|
||||
private let customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,8 +378,19 @@ extension FieldContainer.Virtual where V: FieldOptionalType {
|
||||
*/
|
||||
public init(
|
||||
_ keyPath: KeyPathString,
|
||||
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
|
||||
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
|
||||
customGetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>
|
||||
) -> V
|
||||
)? = nil,
|
||||
customSetter: (
|
||||
(
|
||||
_ object: ObjectProxy<O>,
|
||||
_ field: ObjectProxy<O>.FieldProxy<V>,
|
||||
_ newValue: V
|
||||
) -> Void
|
||||
)? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []) {
|
||||
|
||||
self.init(
|
||||
|
||||
@@ -33,6 +33,14 @@ internal protocol FieldProtocol: PropertyProtocol {
|
||||
|
||||
static var dynamicObjectType: CoreStoreObject.Type { get }
|
||||
|
||||
static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any?
|
||||
static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?)
|
||||
static func read(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject
|
||||
) -> Any?
|
||||
|
||||
static func modify(
|
||||
field: FieldProtocol,
|
||||
for rawObject: CoreStoreManagedObject,
|
||||
newValue: Any?
|
||||
)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,10 @@ public struct From<O: DynamicObject> {
|
||||
*/
|
||||
public init() {
|
||||
|
||||
self.init(entityClass: O.self, configurations: nil)
|
||||
self.init(
|
||||
entityClass: O.self,
|
||||
configurations: nil
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,9 +73,14 @@ public struct From<O: DynamicObject> {
|
||||
```
|
||||
- parameter entity: the associated `NSManagedObject` or `CoreStoreObject` type
|
||||
*/
|
||||
public init(_ entity: O.Type) {
|
||||
|
||||
self.init(entityClass: entity, configurations: nil)
|
||||
public init(
|
||||
_ entity: O.Type
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: entity,
|
||||
configurations: nil
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,9 +91,15 @@ public struct From<O: DynamicObject> {
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `CoreStoreObject`'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: ModelConfiguration, _ otherConfigurations: ModelConfiguration...) {
|
||||
|
||||
self.init(entityClass: O.self, configurations: [configuration] + otherConfigurations)
|
||||
public init(
|
||||
_ configuration: ModelConfiguration,
|
||||
_ otherConfigurations: ModelConfiguration...
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: O.self,
|
||||
configurations: [configuration] + otherConfigurations
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,9 +109,14 @@ public struct From<O: DynamicObject> {
|
||||
```
|
||||
- parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `CoreStoreObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ configurations: [ModelConfiguration]) {
|
||||
|
||||
self.init(entityClass: O.self, configurations: configurations)
|
||||
public init(
|
||||
_ configurations: [ModelConfiguration]
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: O.self,
|
||||
configurations: configurations
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,9 +128,16 @@ public struct From<O: DynamicObject> {
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject` or `CoreStoreObject`'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: O.Type, _ configuration: ModelConfiguration, _ otherConfigurations: ModelConfiguration...) {
|
||||
|
||||
self.init(entityClass: entity, configurations: [configuration] + otherConfigurations)
|
||||
public init(
|
||||
_ entity: O.Type,
|
||||
_ configuration: ModelConfiguration,
|
||||
_ otherConfigurations: ModelConfiguration...
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: entity,
|
||||
configurations: [configuration] + otherConfigurations
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,9 +148,15 @@ public struct From<O: DynamicObject> {
|
||||
- parameter entity: the associated `NSManagedObject` or `CoreStoreObject` 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 `CoreStoreObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ entity: O.Type, _ configurations: [ModelConfiguration]) {
|
||||
|
||||
self.init(entityClass: entity, configurations: configurations)
|
||||
public init(
|
||||
_ entity: O.Type,
|
||||
_ configurations: [ModelConfiguration]
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: entity,
|
||||
configurations: configurations
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -132,14 +164,24 @@ public struct From<O: DynamicObject> {
|
||||
|
||||
internal let findPersistentStores: (_ context: NSManagedObjectContext) -> [NSPersistentStore]?
|
||||
|
||||
internal init(entityClass: O.Type, configurations: [ModelConfiguration]?, findPersistentStores: @escaping (_ context: NSManagedObjectContext) -> [NSPersistentStore]?) {
|
||||
|
||||
internal init(
|
||||
entityClass: O.Type,
|
||||
configurations: [ModelConfiguration]?,
|
||||
findPersistentStores: @escaping (
|
||||
_ context: NSManagedObjectContext
|
||||
) -> [NSPersistentStore]?
|
||||
) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configurations = configurations
|
||||
self.findPersistentStores = findPersistentStores
|
||||
}
|
||||
|
||||
internal func applyToFetchRequest<U>(_ fetchRequest: Internals.CoreStoreFetchRequest<U>, context: NSManagedObjectContext, applyAffectedStores: Bool = true) throws {
|
||||
internal func applyToFetchRequest<U>(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<U>,
|
||||
context: NSManagedObjectContext,
|
||||
applyAffectedStores: Bool = true
|
||||
) throws(CoreStoreError) {
|
||||
|
||||
guard let parentStack = context.parentStack else {
|
||||
|
||||
@@ -158,7 +200,7 @@ public struct From<O: DynamicObject> {
|
||||
|
||||
try self.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
catch let error as CoreStoreError {
|
||||
catch {
|
||||
|
||||
Internals.log(
|
||||
error,
|
||||
@@ -166,14 +208,13 @@ public struct From<O: DynamicObject> {
|
||||
)
|
||||
throw error
|
||||
}
|
||||
catch {
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
internal func applyAffectedStoresForFetchedRequest<U>(_ fetchRequest: Internals.CoreStoreFetchRequest<U>, context: NSManagedObjectContext) throws {
|
||||
|
||||
internal func applyAffectedStoresForFetchedRequest<U>(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<U>,
|
||||
context: NSManagedObjectContext
|
||||
) throws(CoreStoreError) {
|
||||
|
||||
let stores = self.findPersistentStores(context)
|
||||
fetchRequest.affectedStores = stores
|
||||
if stores?.isEmpty == false {
|
||||
@@ -186,8 +227,11 @@ public struct From<O: DynamicObject> {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(entityClass: O.Type, configurations: [ModelConfiguration]?) {
|
||||
|
||||
private init(
|
||||
entityClass: O.Type,
|
||||
configurations: [ModelConfiguration]?
|
||||
) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configurations = configurations
|
||||
|
||||
@@ -211,10 +255,4 @@ public struct From<O: DynamicObject> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
@@ -101,12 +101,6 @@ public struct GroupBy<O: DynamicObject>: GroupByClause, QueryClause, Hashable {
|
||||
|
||||
hasher.combine(self.keyPaths)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
extension GroupBy where O: NSManagedObject {
|
||||
@@ -153,46 +147,6 @@ extension GroupBy where O: CoreStoreObject {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `GroupBy` clause with a key path
|
||||
|
||||
- parameter keyPath: a key path to group results with
|
||||
*/
|
||||
public init<T>(_ keyPath: KeyPath<O, ValueContainer<O>.Required<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `GroupBy` clause with a key path
|
||||
|
||||
- parameter keyPath: a key path to group results with
|
||||
*/
|
||||
public init<T>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `GroupBy` clause with a key path
|
||||
|
||||
- parameter keyPath: a key path to group results with
|
||||
*/
|
||||
public init<T>(_ keyPath: KeyPath<O, TransformableContainer<O>.Required<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `GroupBy` clause with a key path
|
||||
|
||||
- parameter keyPath: a key path to group results with
|
||||
*/
|
||||
public init<T>(_ keyPath: KeyPath<O, TransformableContainer<O>.Optional<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,3 +167,32 @@ public protocol GroupByClause {
|
||||
*/
|
||||
var keyPaths: [KeyPathString] { get }
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension GroupBy where O: CoreStoreObject {
|
||||
|
||||
public init<T>(_ keyPath: KeyPath<O, ValueContainer<O>.Required<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
public init<T>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
public init<T>(_ keyPath: KeyPath<O, TransformableContainer<O>.Required<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
|
||||
public init<T>(_ keyPath: KeyPath<O, TransformableContainer<O>.Optional<T>>) {
|
||||
|
||||
self.init([O.meta[keyPath: keyPath].keyPath])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,15 +66,21 @@ public protocol ImportableObject: DynamicObject {
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
- returns: `true` if an object should be created from `source`. Return `false` to ignore.
|
||||
*/
|
||||
static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool
|
||||
|
||||
static func shouldInsert(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) -> Bool
|
||||
|
||||
/**
|
||||
Implements the actual importing of data from `source`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importObjects(:sourceArray:)` call to be cancelled.
|
||||
|
||||
- parameter source: the object to import from
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
*/
|
||||
func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws
|
||||
func didInsert(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) throws(any Swift.Error)
|
||||
}
|
||||
|
||||
|
||||
@@ -82,8 +88,11 @@ public protocol ImportableObject: DynamicObject {
|
||||
|
||||
extension ImportableObject {
|
||||
|
||||
public static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
|
||||
|
||||
public static func shouldInsert(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) -> Bool {
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +78,11 @@ public protocol ImportableUniqueObject: ImportableObject, Hashable {
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
- returns: `true` if an object should be created from `source`. Return `false` to ignore.
|
||||
*/
|
||||
static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool
|
||||
|
||||
static func shouldInsert(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) -> Bool
|
||||
|
||||
/**
|
||||
Return `true` if an object should be updated from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`.
|
||||
|
||||
@@ -87,8 +90,11 @@ public protocol ImportableUniqueObject: ImportableObject, Hashable {
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
- returns: `true` if an object should be updated from `source`. Return `false` to ignore.
|
||||
*/
|
||||
static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool
|
||||
|
||||
static func shouldUpdate(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) -> Bool
|
||||
|
||||
/**
|
||||
Return the unique ID as extracted from `source`. This method is called before `shouldInsert(from:in:)` or `shouldUpdate(from:in:)`. Return `nil` to skip importing from `source`. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled.
|
||||
|
||||
@@ -96,23 +102,32 @@ public protocol ImportableUniqueObject: ImportableObject, Hashable {
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
- returns: the unique ID as extracted from `source`, or `nil` to skip importing from `source`.
|
||||
*/
|
||||
static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> UniqueIDType?
|
||||
|
||||
static func uniqueID(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) throws(any Swift.Error) -> UniqueIDType?
|
||||
|
||||
/**
|
||||
Implements the actual importing of data from `source`. This method is called just after the object is created and assigned its unique ID as returned from `uniqueID(from:in:)`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. The default implementation simply calls `update(from:in:)`.
|
||||
|
||||
- parameter source: the object to import from
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
*/
|
||||
func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws
|
||||
|
||||
func didInsert(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) throws(any Swift.Error)
|
||||
|
||||
/**
|
||||
Implements the actual importing of data from `source`. This method is called just after the existing object is fetched using its unique ID. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled.
|
||||
|
||||
- parameter source: the object to import from
|
||||
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||
*/
|
||||
func update(from source: ImportSource, in transaction: BaseDataTransaction) throws
|
||||
func update(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) throws(any Swift.Error)
|
||||
}
|
||||
|
||||
|
||||
@@ -146,18 +161,27 @@ extension ImportableUniqueObject where UniqueIDType.QueryableNativeType: CoreDat
|
||||
|
||||
extension ImportableUniqueObject {
|
||||
|
||||
public static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
|
||||
|
||||
public static func shouldInsert(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) -> Bool {
|
||||
|
||||
return Self.shouldUpdate(from: source, in: transaction)
|
||||
}
|
||||
|
||||
public static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool{
|
||||
|
||||
public static func shouldUpdate(
|
||||
from source: ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) -> Bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public func didInsert(from source: Self.ImportSource, in transaction: BaseDataTransaction) throws {
|
||||
|
||||
public func didInsert(
|
||||
from source: Self.ImportSource,
|
||||
in transaction: BaseDataTransaction
|
||||
) throws(any Swift.Error) {
|
||||
|
||||
try self.update(from: source, in: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,14 @@ public final class InferredSchemaMappingProvider: Hashable, SchemaMappingProvide
|
||||
|
||||
// MARK: SchemaMappingProvider
|
||||
|
||||
public func cs_createMappingModel(from sourceSchema: DynamicSchema, to destinationSchema: DynamicSchema, storage: LocalStorage) throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
|
||||
public func cs_createMappingModel(
|
||||
from sourceSchema: DynamicSchema,
|
||||
to destinationSchema: DynamicSchema,
|
||||
storage: LocalStorage
|
||||
) throws(CoreStoreError) -> (
|
||||
mappingModel: NSMappingModel,
|
||||
migrationType: MigrationType
|
||||
) {
|
||||
|
||||
let sourceModel = sourceSchema.rawModel()
|
||||
let destinationModel = destinationSchema.rawModel()
|
||||
|
||||
@@ -77,8 +77,8 @@ extension Internals {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func performFetchFromSpecifiedStores() throws {
|
||||
|
||||
internal func performFetchFromSpecifiedStores() throws(any Swift.Error) {
|
||||
|
||||
try self.reapplyAffectedStores(self.typedFetchRequest, self.managedObjectContext)
|
||||
try self.performFetch()
|
||||
|
||||
@@ -103,6 +103,9 @@ extension Internals {
|
||||
// MARK: Private
|
||||
|
||||
@nonobjc
|
||||
private let reapplyAffectedStores: (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>, _ context: NSManagedObjectContext) throws -> Void
|
||||
private let reapplyAffectedStores: (
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>,
|
||||
_ context: NSManagedObjectContext
|
||||
) throws(any Swift.Error) -> Void
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
var elementUpdated: [ElementPath]
|
||||
var elementMoved: [(source: ElementPath, target: ElementPath)]
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
init(
|
||||
data: C,
|
||||
sectionDeleted: [Int] = [],
|
||||
|
||||
@@ -190,7 +190,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
internal init(
|
||||
deleted: [Index] = [],
|
||||
inserted: [Index] = [],
|
||||
@@ -213,18 +213,18 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
|
||||
// Implementation based on https://github.com/ra1028/DifferenceKit
|
||||
@usableFromInline
|
||||
internal struct Trace<Index> {
|
||||
|
||||
internal struct Trace<I> {
|
||||
|
||||
@usableFromInline
|
||||
internal var reference: Index?
|
||||
|
||||
internal var reference: I?
|
||||
|
||||
@usableFromInline
|
||||
internal var deleteOffset = 0
|
||||
|
||||
@usableFromInline
|
||||
internal var isTracked = false
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
init() {}
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
@usableFromInline
|
||||
internal var position = 0
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
internal init(_ indices: ContiguousArray<Int>) {
|
||||
|
||||
self.indices = indices
|
||||
@@ -292,7 +292,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
@usableFromInline
|
||||
internal let pointer: UnsafePointer<T>
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
internal init(pointer: UnsafePointer<T>) {
|
||||
|
||||
self.pointeeHashValue = pointer.pointee.hashValue
|
||||
|
||||
@@ -40,7 +40,7 @@ extension Internals.DiffableDataUIDispatcher {
|
||||
@usableFromInline
|
||||
var changesets: ContiguousArray<Changeset<C>>
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
init<S: Sequence>(_ changesets: S) where S.Element == Changeset<C> {
|
||||
|
||||
self.changesets = ContiguousArray(changesets)
|
||||
|
||||
@@ -106,24 +106,23 @@ extension Internals {
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(QuartzCore)
|
||||
#if os(watchOS) || !canImport(QuartzCore)
|
||||
|
||||
performDiffingUpdates()
|
||||
|
||||
#else
|
||||
|
||||
CATransaction.begin()
|
||||
|
||||
|
||||
if !animatingDifferences {
|
||||
|
||||
|
||||
CATransaction.setDisableActions(true)
|
||||
}
|
||||
performDiffingUpdates()
|
||||
|
||||
|
||||
CATransaction.commit()
|
||||
|
||||
#else
|
||||
|
||||
performDiffingUpdates()
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +220,7 @@ extension Internals {
|
||||
@usableFromInline
|
||||
var section: Int
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
init(element: Int, section: Int) {
|
||||
|
||||
self.element = element
|
||||
|
||||
@@ -74,7 +74,7 @@ extension Internals {
|
||||
default:
|
||||
Internals.abort("\(Internals.typeName(DynamicObject.self)) is not meant to be implemented by external types.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal init(_ entityDescription: NSEntityDescription) {
|
||||
|
||||
|
||||
@@ -91,11 +91,14 @@ extension Internals {
|
||||
// MARK: NSFetchedResultsControllerDelegate
|
||||
|
||||
@objc
|
||||
dynamic func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
dynamic func controllerDidChangeContent(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>
|
||||
) {
|
||||
|
||||
var snapshot = Internals.DiffableDataSourceSnapshot(
|
||||
sections: controller.sections ?? [],
|
||||
sectionIndexTransformer: self.handler.map({ $0.sectionIndexTransformer }) ?? { _ in nil },
|
||||
sectionIndexTransformer: self.handler
|
||||
.map({ $0.sectionIndexTransformer }) ?? { _ in nil },
|
||||
fetchOffset: controller.fetchRequest.fetchOffset,
|
||||
fetchLimit: controller.fetchRequest.fetchLimit
|
||||
)
|
||||
@@ -117,13 +120,24 @@ extension Internals {
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
|
||||
dynamic func controller(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>,
|
||||
didChange anObject: Any,
|
||||
at indexPath: IndexPath?,
|
||||
for type: NSFetchedResultsChangeType,
|
||||
newIndexPath: IndexPath?
|
||||
) {
|
||||
|
||||
let object = anObject as! NSManagedObject
|
||||
self.reloadedItemIDs.append(object.objectID)
|
||||
}
|
||||
|
||||
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
|
||||
func controller(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>,
|
||||
didChange sectionInfo: NSFetchedResultsSectionInfo,
|
||||
atSectionIndex sectionIndex: Int,
|
||||
for type: NSFetchedResultsChangeType
|
||||
) {
|
||||
|
||||
self.reloadedSectionIDs.append(sectionInfo.name)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,9 @@ extension Internals {
|
||||
// MARK: NSFetchedResultsControllerDelegate
|
||||
|
||||
@objc
|
||||
dynamic func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
dynamic func controllerWillChangeContent(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>
|
||||
) {
|
||||
|
||||
self.taskGroup.enter()
|
||||
guard self.enabled else {
|
||||
@@ -107,7 +109,9 @@ extension Internals {
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
dynamic func controllerDidChangeContent(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>
|
||||
) {
|
||||
|
||||
defer {
|
||||
|
||||
@@ -121,7 +125,13 @@ extension Internals {
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
|
||||
dynamic func controller(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>,
|
||||
didChange anObject: Any,
|
||||
at indexPath: IndexPath?,
|
||||
for type: NSFetchedResultsChangeType,
|
||||
newIndexPath: IndexPath?
|
||||
) {
|
||||
|
||||
guard self.enabled else {
|
||||
|
||||
@@ -137,7 +147,12 @@ extension Internals {
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
|
||||
dynamic func controller(
|
||||
_ controller: NSFetchedResultsController<NSFetchRequestResult>,
|
||||
didChange sectionInfo: NSFetchedResultsSectionInfo,
|
||||
atSectionIndex sectionIndex: Int,
|
||||
for type: NSFetchedResultsChangeType
|
||||
) {
|
||||
|
||||
guard self.enabled else {
|
||||
|
||||
|
||||
@@ -55,11 +55,18 @@ extension Internals {
|
||||
|
||||
// MARK: NSMigrationManager
|
||||
|
||||
init(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, progress: Progress) {
|
||||
init(
|
||||
sourceModel: NSManagedObjectModel,
|
||||
destinationModel: NSManagedObjectModel,
|
||||
progress: Progress
|
||||
) {
|
||||
|
||||
self.progress = progress
|
||||
|
||||
super.init(sourceModel: sourceModel, destinationModel: destinationModel)
|
||||
super.init(
|
||||
sourceModel: sourceModel,
|
||||
destinationModel: destinationModel
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,12 @@ extension Internals {
|
||||
|
||||
let observer: NSObjectProtocol
|
||||
|
||||
init(notificationName: Notification.Name, object: Any?, queue: OperationQueue? = nil, closure: @escaping (_ note: Notification) -> Void) {
|
||||
init(
|
||||
notificationName: Notification.Name,
|
||||
object: Any?,
|
||||
queue: OperationQueue? = nil,
|
||||
closure: @escaping (_ note: Notification) -> Void
|
||||
) {
|
||||
|
||||
self.observer = NotificationCenter.default.addObserver(
|
||||
forName: notificationName,
|
||||
|
||||
@@ -35,7 +35,12 @@ extension Internals {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(notificationName: Notification.Name, object: Any?, queue: OperationQueue? = nil, sharedValue: @escaping (_ note: Notification) -> T) {
|
||||
internal init(
|
||||
notificationName: Notification.Name,
|
||||
object: Any?,
|
||||
queue: OperationQueue? = nil,
|
||||
sharedValue: @escaping (_ note: Notification) -> T
|
||||
) {
|
||||
|
||||
self.observer = NotificationCenter.default.addObserver(
|
||||
forName: notificationName,
|
||||
@@ -59,9 +64,15 @@ extension Internals {
|
||||
self.observers.removeAllObjects()
|
||||
}
|
||||
|
||||
internal func addObserver<U: AnyObject>(_ observer: U, closure: @escaping (T) -> Void) {
|
||||
internal func addObserver<U: AnyObject>(
|
||||
_ observer: U,
|
||||
closure: @escaping (T) -> Void
|
||||
) {
|
||||
|
||||
self.observers.setObject(Closure<T, Void>(closure), forKey: observer)
|
||||
self.observers.setObject(
|
||||
Closure<T, Void>(closure),
|
||||
forKey: observer
|
||||
)
|
||||
}
|
||||
|
||||
internal func removeObserver<U: AnyObject>(_ observer: U) {
|
||||
|
||||
@@ -39,8 +39,6 @@ internal enum Internals {
|
||||
return object_getClass(instance) as! T.Type
|
||||
}
|
||||
|
||||
// MARK: Associated Objects
|
||||
|
||||
@inline(__always)
|
||||
internal static func getAssociatedObjectForKey<T: AnyObject>(_ key: UnsafeRawPointer, inObject object: Any) -> T? {
|
||||
|
||||
@@ -123,4 +121,47 @@ internal enum Internals {
|
||||
|
||||
return closure()
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func autoreleasepool<T>(
|
||||
_ closure: () -> T
|
||||
) -> T {
|
||||
|
||||
return ObjectiveC.autoreleasepool(invoking: closure)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func autoreleasepool<T>(
|
||||
_ closure: () throws(any Swift.Error) -> T
|
||||
) throws(any Swift.Error) -> T {
|
||||
|
||||
return try ObjectiveC.autoreleasepool(invoking: closure)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func autoreleasepool<T>(
|
||||
_ closure: () throws(CoreStoreError) -> T
|
||||
) throws(CoreStoreError) -> T {
|
||||
|
||||
do {
|
||||
|
||||
return try ObjectiveC.autoreleasepool(invoking: closure)
|
||||
}
|
||||
catch {
|
||||
|
||||
throw CoreStoreError(error)
|
||||
}
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func withCheckedThrowingContinuation<T>(
|
||||
function: String = #function,
|
||||
_ body: (CheckedContinuation<T, any Swift.Error>) -> Void
|
||||
) async throws(any Swift.Error) -> T {
|
||||
|
||||
return try await _Concurrency.withCheckedThrowingContinuation(
|
||||
function: function,
|
||||
body
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,11 @@ public struct Into<O: DynamicObject>: Hashable {
|
||||
*/
|
||||
public init() {
|
||||
|
||||
self.init(entityClass: O.self, configuration: nil, inferStoreIfPossible: true)
|
||||
self.init(
|
||||
entityClass: O.self,
|
||||
configuration: nil,
|
||||
inferStoreIfPossible: true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,9 +74,15 @@ public struct Into<O: DynamicObject>: Hashable {
|
||||
```
|
||||
- parameter entity: the `NSManagedObject` or `CoreStoreObject` type to be created
|
||||
*/
|
||||
public init(_ entity: O.Type) {
|
||||
|
||||
self.init(entityClass: entity, configuration: nil, inferStoreIfPossible: true)
|
||||
public init(
|
||||
_ entity: O.Type
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: entity,
|
||||
configuration: nil,
|
||||
inferStoreIfPossible: true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,9 +92,15 @@ public struct Into<O: DynamicObject>: Hashable {
|
||||
```
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s or `CoreStoreObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ configuration: ModelConfiguration) {
|
||||
|
||||
self.init(entityClass: O.self, configuration: configuration, inferStoreIfPossible: false)
|
||||
public init(
|
||||
_ configuration: ModelConfiguration
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: O.self,
|
||||
configuration: configuration,
|
||||
inferStoreIfPossible: false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,9 +111,16 @@ public struct Into<O: DynamicObject>: Hashable {
|
||||
- parameter entity: the `NSManagedObject` or `CoreStoreObject` 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 or `CoreStoreObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
public init(_ entity: O.Type, _ configuration: ModelConfiguration) {
|
||||
|
||||
self.init(entityClass: entity, configuration: configuration, inferStoreIfPossible: false)
|
||||
public init(
|
||||
_ entity: O.Type,
|
||||
_ configuration: ModelConfiguration
|
||||
) {
|
||||
|
||||
self.init(
|
||||
entityClass: entity,
|
||||
configuration: configuration,
|
||||
inferStoreIfPossible: false
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -125,16 +148,14 @@ public struct Into<O: DynamicObject>: Hashable {
|
||||
|
||||
internal let inferStoreIfPossible: Bool
|
||||
|
||||
internal init(entityClass: O.Type, configuration: ModelConfiguration, inferStoreIfPossible: Bool) {
|
||||
|
||||
internal init(
|
||||
entityClass: O.Type,
|
||||
configuration: ModelConfiguration,
|
||||
inferStoreIfPossible: Bool
|
||||
) {
|
||||
|
||||
self.entityClass = entityClass
|
||||
self.configuration = configuration
|
||||
self.inferStoreIfPossible = inferStoreIfPossible
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -317,9 +317,3 @@ extension NSSet: AllowedObjectiveCToManyRelationshipKeyPathValue {}
|
||||
extension NSOrderedSet: AllowedObjectiveCToManyRelationshipKeyPathValue {}
|
||||
|
||||
extension Optional: AllowedObjectiveCToManyRelationshipKeyPathValue where Wrapped: AllowedObjectiveCToManyRelationshipKeyPathValue, Wrapped: AllowedObjectiveCRelationshipKeyPathValue {}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "AllowedObjectiveCToManyRelationshipKeyPathValue")
|
||||
public typealias AllowedCoreStoreObjectCollectionKeyPathValue = AllowedObjectiveCToManyRelationshipKeyPathValue
|
||||
|
||||
@@ -92,12 +92,3 @@ public protocol RelationshipKeyPathStringConvertible: KeyPathStringConvertible {
|
||||
*/
|
||||
public protocol ToManyRelationshipKeyPathStringConvertible: RelationshipKeyPathStringConvertible where ReturnValueType: Sequence {}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "AnyKeyPathStringConvertible")
|
||||
public typealias AnyDynamicKeyPath = AnyKeyPathStringConvertible
|
||||
|
||||
@available(*, deprecated, renamed: "KeyPathStringConvertible")
|
||||
public typealias DynamicKeyPath = KeyPathStringConvertible
|
||||
|
||||
|
||||
@@ -1440,21 +1440,6 @@ extension ListMonitor where O: NSManagedObject {
|
||||
|
||||
return self.sectionInfo(safelyAt: section)?.objects as! [O]?
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "objects(in:)")
|
||||
public func objectsInSection(_ section: Int) -> [O] {
|
||||
|
||||
return self.objects(in: section)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "objects(safelyIn:)")
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [O]? {
|
||||
|
||||
return self.objects(safelyIn: section)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1500,12 +1485,6 @@ extension ListMonitor where O: CoreStoreObject {
|
||||
return (self.sectionInfo(safelyAt: section)?.objects)?
|
||||
.map({ O.cs_fromRaw(object: $0 as! NSManagedObject) })
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -95,8 +95,10 @@ extension ListPublisher.ReactiveNamespace {
|
||||
- parameter emitInitialValue: If `true`, the current value is immediately emitted to the first subscriber. If `false`, the event fires only starting the next `ListSnapshot` update.
|
||||
- returns: A `Publisher` that emits a `ListSnapshot` whenever changes occur in the `ListPublisher`.
|
||||
*/
|
||||
public func snapshot(emitInitialValue: Bool = true) -> ListPublisher.SnapshotPublisher {
|
||||
|
||||
public func snapshot(
|
||||
emitInitialValue: Bool = true
|
||||
) -> ListPublisher.SnapshotPublisher {
|
||||
|
||||
return .init(
|
||||
listPublisher: self.base,
|
||||
emitInitialValue: emitInitialValue
|
||||
|
||||
@@ -52,8 +52,10 @@ extension ListPublisher {
|
||||
public typealias Output = ListSnapshot<O>
|
||||
public typealias Failure = Never
|
||||
|
||||
public func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
|
||||
|
||||
public func receive<S: Subscriber>(
|
||||
subscriber: S
|
||||
) where S.Input == Output, S.Failure == Failure {
|
||||
|
||||
subscriber.receive(
|
||||
subscription: ListSnapshotSubscription(
|
||||
publisher: self.listPublisher,
|
||||
|
||||
@@ -186,7 +186,7 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
|
||||
public func refetch<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B,
|
||||
sourceIdentifier: Any? = nil
|
||||
) throws where B.ObjectType == O {
|
||||
) throws(any Swift.Error) where B.ObjectType == O {
|
||||
|
||||
try self.refetch(
|
||||
from: clauseChain.from,
|
||||
@@ -215,7 +215,7 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
|
||||
public func refetch<B: SectionMonitorBuilderType>(
|
||||
_ clauseChain: B,
|
||||
sourceIdentifier: Any? = nil
|
||||
) throws where B.ObjectType == O {
|
||||
) throws(any Swift.Error) where B.ObjectType == O {
|
||||
|
||||
try self.refetch(
|
||||
from: clauseChain.from,
|
||||
@@ -343,7 +343,7 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
|
||||
sectionBy: SectionBy<O>?,
|
||||
applyFetchClauses: @escaping (_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObject>) -> Void,
|
||||
sourceIdentifier: Any?
|
||||
) throws {
|
||||
) throws(any Swift.Error) {
|
||||
|
||||
let (newFetchedResultsController, newFetchedResultsControllerDelegate) = Self.recreateFetchedResultsController(
|
||||
context: self.fetchedResultsController.managedObjectContext,
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,12 @@ import Foundation
|
||||
extension NSEntityDescription {
|
||||
|
||||
@nonobjc
|
||||
internal func cs_resolveAttributeNames() -> [String: (attribute: NSAttributeDescription, versionHash: Data)] {
|
||||
internal func cs_resolveAttributeNames() -> [
|
||||
String: (
|
||||
attribute: NSAttributeDescription,
|
||||
versionHash: Data
|
||||
)
|
||||
] {
|
||||
|
||||
return self.attributesByName.reduce(
|
||||
into: [:],
|
||||
@@ -44,7 +49,12 @@ extension NSEntityDescription {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func cs_resolveAttributeRenamingIdentities() -> [String: (attribute: NSAttributeDescription, versionHash: Data)] {
|
||||
internal func cs_resolveAttributeRenamingIdentities() -> [
|
||||
String: (
|
||||
attribute: NSAttributeDescription,
|
||||
versionHash: Data
|
||||
)
|
||||
] {
|
||||
|
||||
return self.attributesByName.reduce(
|
||||
into: [:],
|
||||
@@ -56,7 +66,12 @@ extension NSEntityDescription {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func cs_resolveRelationshipNames() -> [String: (relationship: NSRelationshipDescription, versionHash: Data)] {
|
||||
internal func cs_resolveRelationshipNames() -> [
|
||||
String: (
|
||||
relationship: NSRelationshipDescription,
|
||||
versionHash: Data
|
||||
)
|
||||
] {
|
||||
|
||||
return self.relationshipsByName.reduce(
|
||||
into: [:],
|
||||
@@ -68,7 +83,12 @@ extension NSEntityDescription {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func cs_resolveRelationshipRenamingIdentities() -> [String: (relationship: NSRelationshipDescription, versionHash: Data)] {
|
||||
internal func cs_resolveRelationshipRenamingIdentities() -> [
|
||||
String: (
|
||||
relationship: NSRelationshipDescription,
|
||||
versionHash: Data
|
||||
)
|
||||
] {
|
||||
|
||||
return self.relationshipsByName.reduce(
|
||||
into: [:],
|
||||
|
||||
@@ -41,8 +41,12 @@ extension DataStack {
|
||||
- returns: an `NSFetchedResultsController` that observes the `DataStack`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.mainContext,
|
||||
from: from,
|
||||
@@ -61,8 +65,12 @@ extension DataStack {
|
||||
- returns: an `NSFetchedResultsController` that observes the `DataStack`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.mainContext,
|
||||
from: from,
|
||||
@@ -80,8 +88,11 @@ extension DataStack {
|
||||
- returns: an `NSFetchedResultsController` that observes the `DataStack`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.mainContext,
|
||||
from: from,
|
||||
@@ -99,8 +110,12 @@ extension DataStack {
|
||||
- returns: an `NSFetchedResultsController` that observes the `DataStack`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(forDataStack dataStack: DataStack, _ from: From<O>, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
forDataStack dataStack: DataStack,
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.mainContext,
|
||||
from: from,
|
||||
@@ -125,8 +140,12 @@ extension UnsafeDataTransaction {
|
||||
- returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.context,
|
||||
from: from,
|
||||
@@ -145,8 +164,12 @@ extension UnsafeDataTransaction {
|
||||
- returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ sectionBy: SectionBy<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.context,
|
||||
from: from,
|
||||
@@ -164,8 +187,11 @@ extension UnsafeDataTransaction {
|
||||
- returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.context,
|
||||
from: from,
|
||||
@@ -183,8 +209,11 @@ extension UnsafeDataTransaction {
|
||||
- returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
|
||||
*/
|
||||
@nonobjc
|
||||
public func createFetchedResultsController<O: NSManagedObject>(_ from: From<O>, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<O> {
|
||||
|
||||
public func createFetchedResultsController<O: NSManagedObject>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
return Internals.createFRC(
|
||||
fromContext: self.context,
|
||||
from: from,
|
||||
@@ -202,7 +231,12 @@ extension Internals {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate static func createFRC<O: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<O>, sectionBy: SectionBy<O>? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<O> {
|
||||
fileprivate static func createFRC<O: NSManagedObject>(
|
||||
fromContext context: NSManagedObjectContext,
|
||||
from: From<O>,
|
||||
sectionBy: SectionBy<O>? = nil,
|
||||
fetchClauses: [FetchClause]
|
||||
) -> NSFetchedResultsController<O> {
|
||||
|
||||
let controller = Internals.CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
|
||||
@@ -84,8 +84,10 @@ extension NSManagedObject {
|
||||
- returns: the primitive value for the KVC key
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func getValue(forKvcKey kvcKey: KeyPathString) -> Any? {
|
||||
|
||||
public func getValue(
|
||||
forKvcKey kvcKey: KeyPathString
|
||||
) -> Any? {
|
||||
|
||||
self.willAccessValue(forKey: kvcKey)
|
||||
defer {
|
||||
|
||||
@@ -102,8 +104,11 @@ extension NSManagedObject {
|
||||
- returns: the primitive value transformed by the `didGetValue` closure
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func getValue<T>(forKvcKey kvcKey: KeyPathString, didGetValue: (Any?) throws -> T) rethrows -> T {
|
||||
|
||||
public func getValue<T>(
|
||||
forKvcKey kvcKey: KeyPathString,
|
||||
didGetValue: (Any?) throws(any Swift.Error) -> T
|
||||
) rethrows -> T {
|
||||
|
||||
self.willAccessValue(forKey: kvcKey)
|
||||
defer {
|
||||
|
||||
@@ -121,8 +126,12 @@ extension NSManagedObject {
|
||||
- returns: the primitive value transformed by the `didGetValue` closure
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func getValue<T>(forKvcKey kvcKey: KeyPathString, willGetValue: () throws -> Void, didGetValue: (Any?) throws -> T) rethrows -> T {
|
||||
|
||||
public func getValue<T>(
|
||||
forKvcKey kvcKey: KeyPathString,
|
||||
willGetValue: () throws(any Swift.Error) -> Void,
|
||||
didGetValue: (Any?) throws(any Swift.Error) -> T
|
||||
) rethrows -> T {
|
||||
|
||||
self.willAccessValue(forKey: kvcKey)
|
||||
defer {
|
||||
|
||||
@@ -139,8 +148,11 @@ extension NSManagedObject {
|
||||
- parameter KVCKey: the KVC key
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPathString) {
|
||||
|
||||
public func setValue(
|
||||
_ value: Any?,
|
||||
forKvcKey KVCKey: KeyPathString
|
||||
) {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
|
||||
@@ -157,8 +169,12 @@ extension NSManagedObject {
|
||||
- parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`.
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPathString, didSetValue: () -> Void) {
|
||||
|
||||
public func setValue(
|
||||
_ value: Any?,
|
||||
forKvcKey KVCKey: KeyPathString,
|
||||
didSetValue: () -> Void
|
||||
) {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
|
||||
@@ -177,8 +193,13 @@ extension NSManagedObject {
|
||||
- parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`.
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func setValue<T>(_ value: T, forKvcKey KVCKey: KeyPathString, willSetValue: (T) throws -> Any?, didSetValue: (Any?) -> Void = { _ in }) rethrows {
|
||||
|
||||
public func setValue<T>(
|
||||
_ value: T,
|
||||
forKvcKey KVCKey: KeyPathString,
|
||||
willSetValue: (T) throws(any Swift.Error) -> Any?,
|
||||
didSetValue: (Any?) -> Void = { _ in }
|
||||
) rethrows {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
|
||||
|
||||
@@ -34,8 +34,10 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
// MARK: FetchableSource
|
||||
|
||||
@nonobjc
|
||||
public func fetchExisting<O: DynamicObject>(_ object: O) -> O? {
|
||||
|
||||
public func fetchExisting<O: DynamicObject>(
|
||||
_ object: O
|
||||
) -> O? {
|
||||
|
||||
let rawObject = object.cs_toRaw()
|
||||
if rawObject.objectID.isTemporaryID {
|
||||
|
||||
@@ -75,8 +77,10 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchExisting<O: DynamicObject>(_ objectID: NSManagedObjectID) -> O? {
|
||||
|
||||
public func fetchExisting<O: DynamicObject>(
|
||||
_ objectID: NSManagedObjectID
|
||||
) -> O? {
|
||||
|
||||
do {
|
||||
|
||||
let existingObject = try self.existingObject(with: objectID)
|
||||
@@ -89,26 +93,36 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objects: S) -> [O] where S.Iterator.Element == O {
|
||||
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objects: S
|
||||
) -> [O] where S.Iterator.Element == O {
|
||||
|
||||
return objects.compactMap({ self.fetchExisting($0.cs_id()) })
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objectIDs: S) -> [O] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
public func fetchExisting<O: DynamicObject, S: Sequence>(
|
||||
_ objectIDs: S
|
||||
) -> [O] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
return objectIDs.compactMap({ self.fetchExisting($0) })
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> O? {
|
||||
|
||||
public func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
return try self.fetchOne(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> O? {
|
||||
|
||||
public func fetchOne<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObject>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -120,20 +134,31 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> B.ObjectType? {
|
||||
|
||||
return try self.fetchOne(clauseChain.from, clauseChain.fetchClauses)
|
||||
public func fetchOne<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ObjectType? {
|
||||
|
||||
return try self.fetchOne(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [O] {
|
||||
|
||||
public func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
return try self.fetchAll(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [O] {
|
||||
|
||||
public func fetchAll<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObject>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -146,20 +171,31 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [B.ObjectType] {
|
||||
|
||||
return try self.fetchAll(clauseChain.from, clauseChain.fetchClauses)
|
||||
public func fetchAll<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [B.ObjectType] {
|
||||
|
||||
return try self.fetchAll(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> Int {
|
||||
|
||||
public func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
return try self.fetchCount(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> Int {
|
||||
|
||||
public func fetchCount<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSNumber>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -170,20 +206,31 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
|
||||
|
||||
return try self.fetchCount(clauseChain.from, clauseChain.fetchClauses)
|
||||
public func fetchCount<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
return try self.fetchCount(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
return try self.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
|
||||
|
||||
public func fetchObjectID<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObjectID>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -195,19 +242,30 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> NSManagedObjectID? {
|
||||
|
||||
return try self.fetchObjectID(clauseChain.from, clauseChain.fetchClauses)
|
||||
public func fetchObjectID<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
return try self.fetchObjectID(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
|
||||
|
||||
public func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: FetchClause...
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
return try self.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
|
||||
public func fetchObjectIDs<O>(
|
||||
_ from: From<O>,
|
||||
_ fetchClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObjectID>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -220,14 +278,21 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [NSManagedObjectID] {
|
||||
|
||||
return try self.fetchObjectIDs(clauseChain.from, clauseChain.fetchClauses)
|
||||
public func fetchObjectIDs<B: FetchChainableBuilderType>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
return try self.fetchObjectIDs(
|
||||
clauseChain.from,
|
||||
clauseChain.fetchClauses
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func fetchObjectIDs(_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObjectID>) throws -> [NSManagedObjectID] {
|
||||
|
||||
internal func fetchObjectIDs(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObjectID>
|
||||
) throws(CoreStoreError) -> [NSManagedObjectID] {
|
||||
|
||||
var fetchResults: [NSManagedObjectID]?
|
||||
var fetchError: Error?
|
||||
self.performAndWait {
|
||||
@@ -257,14 +322,22 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
// MARK: QueryableSource
|
||||
|
||||
@nonobjc
|
||||
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: QueryClause...) throws -> U? {
|
||||
|
||||
public func queryValue<O, U: QueryableAttributeType>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, U>,
|
||||
_ queryClauses: QueryClause...
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
return try self.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: [QueryClause]) throws -> U? {
|
||||
|
||||
public func queryValue<O, U: QueryableAttributeType>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, U>,
|
||||
_ queryClauses: [QueryClause]
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSDictionary>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -277,20 +350,34 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryValue<B>(_ clauseChain: B) throws -> B.ResultType? where B: QueryChainableBuilderType, B.ResultType: QueryableAttributeType {
|
||||
|
||||
return try self.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||
public func queryValue<B>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> B.ResultType? where B: QueryChainableBuilderType, B.ResultType: QueryableAttributeType {
|
||||
|
||||
return try self.queryValue(
|
||||
clauseChain.from,
|
||||
clauseChain.select,
|
||||
clauseChain.queryClauses
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
|
||||
|
||||
public func queryAttributes<O>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, NSDictionary>,
|
||||
_ queryClauses: QueryClause...
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
return try self.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
|
||||
|
||||
public func queryAttributes<O>(
|
||||
_ from: From<O>,
|
||||
_ selectClause: Select<O, NSDictionary>,
|
||||
_ queryClauses: [QueryClause]
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSDictionary>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -302,9 +389,15 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
return try self.queryAttributes(fetchRequest)
|
||||
}
|
||||
|
||||
public func queryAttributes<B>(_ clauseChain: B) throws -> [[String : Any]] where B : QueryChainableBuilderType, B.ResultType == NSDictionary {
|
||||
|
||||
return try self.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||
public func queryAttributes<B>(
|
||||
_ clauseChain: B
|
||||
) throws(CoreStoreError) -> [[String : Any]] where B : QueryChainableBuilderType, B.ResultType == NSDictionary {
|
||||
|
||||
return try self.queryAttributes(
|
||||
clauseChain.from,
|
||||
clauseChain.select,
|
||||
clauseChain.queryClauses
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -320,8 +413,11 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
// MARK: Deleting
|
||||
|
||||
@nonobjc
|
||||
internal func deleteAll<O>(_ from: From<O>, _ deleteClauses: [FetchClause]) throws -> Int {
|
||||
|
||||
internal func deleteAll<O>(
|
||||
_ from: From<O>,
|
||||
_ deleteClauses: [FetchClause]
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
let fetchRequest = Internals.CoreStoreFetchRequest<NSManagedObject>()
|
||||
try from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -343,10 +439,12 @@ extension NSManagedObjectContext {
|
||||
// MARK: Fetching
|
||||
|
||||
@nonobjc
|
||||
internal func fetchOne<O: NSManagedObject>(_ fetchRequest: Internals.CoreStoreFetchRequest<O>) throws -> O? {
|
||||
|
||||
internal func fetchOne<O: NSManagedObject>(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<O>
|
||||
) throws(CoreStoreError) -> O? {
|
||||
|
||||
var fetchResults: [O]?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -371,10 +469,12 @@ extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func fetchAll<O: NSManagedObject>(_ fetchRequest: Internals.CoreStoreFetchRequest<O>) throws -> [O] {
|
||||
|
||||
internal func fetchAll<O: NSManagedObject>(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<O>
|
||||
) throws(CoreStoreError) -> [O] {
|
||||
|
||||
var fetchResults: [O]?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -399,10 +499,12 @@ extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func fetchCount(_ fetchRequest: Internals.CoreStoreFetchRequest<NSNumber>) throws -> Int {
|
||||
|
||||
internal func fetchCount(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<NSNumber>
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
var count = 0
|
||||
var countError: Error?
|
||||
var countError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -427,10 +529,12 @@ extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func fetchObjectID(_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObjectID>) throws -> NSManagedObjectID? {
|
||||
|
||||
internal func fetchObjectID(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<NSManagedObjectID>
|
||||
) throws(CoreStoreError) -> NSManagedObjectID? {
|
||||
|
||||
var fetchResults: [NSManagedObjectID]?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -458,10 +562,13 @@ extension NSManagedObjectContext {
|
||||
// MARK: Querying
|
||||
|
||||
@nonobjc
|
||||
internal func queryValue<O, U: QueryableAttributeType>(_ selectTerms: [SelectTerm<O>], fetchRequest: Internals.CoreStoreFetchRequest<NSDictionary>) throws -> U? {
|
||||
|
||||
internal func queryValue<O, U: QueryableAttributeType>(
|
||||
_ selectTerms: [SelectTerm<O>],
|
||||
fetchRequest: Internals.CoreStoreFetchRequest<NSDictionary>
|
||||
) throws(CoreStoreError) -> U? {
|
||||
|
||||
var fetchResults: [Any]?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -491,10 +598,13 @@ extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func queryValue<O>(_ selectTerms: [SelectTerm<O>], fetchRequest: Internals.CoreStoreFetchRequest<NSDictionary>) throws -> Any? {
|
||||
|
||||
internal func queryValue<O>(
|
||||
_ selectTerms: [SelectTerm<O>],
|
||||
fetchRequest: Internals.CoreStoreFetchRequest<NSDictionary>
|
||||
) throws(CoreStoreError) -> Any? {
|
||||
|
||||
var fetchResults: [Any]?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -524,10 +634,12 @@ extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func queryAttributes(_ fetchRequest: Internals.CoreStoreFetchRequest<NSDictionary>) throws -> [[String: Any]] {
|
||||
|
||||
internal func queryAttributes(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<NSDictionary>
|
||||
) throws(CoreStoreError) -> [[String: Any]] {
|
||||
|
||||
var fetchResults: [Any]?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
do {
|
||||
@@ -555,14 +667,16 @@ extension NSManagedObjectContext {
|
||||
// MARK: Deleting
|
||||
|
||||
@nonobjc
|
||||
internal func deleteAll<O: NSManagedObject>(_ fetchRequest: Internals.CoreStoreFetchRequest<O>) throws -> Int {
|
||||
|
||||
internal func deleteAll<O: NSManagedObject>(
|
||||
_ fetchRequest: Internals.CoreStoreFetchRequest<O>
|
||||
) throws(CoreStoreError) -> Int {
|
||||
|
||||
var numberOfDeletedObjects: Int?
|
||||
var fetchError: Error?
|
||||
var fetchError: (any Swift.Error)?
|
||||
self.performAndWait {
|
||||
|
||||
autoreleasepool {
|
||||
|
||||
Internals.autoreleasepool {
|
||||
|
||||
do {
|
||||
|
||||
let fetchResults = try self.fetch(fetchRequest.staticCast())
|
||||
|
||||
@@ -32,14 +32,18 @@ import CoreData
|
||||
extension NSPersistentStoreCoordinator {
|
||||
|
||||
@nonobjc
|
||||
internal func performAsynchronously(_ closure: @escaping () -> Void) {
|
||||
|
||||
internal func performAsynchronously(
|
||||
_ closure: @escaping () -> Void
|
||||
) {
|
||||
|
||||
self.perform(closure)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func performSynchronously<T>(_ closure: @escaping () -> T) -> T {
|
||||
|
||||
internal func performSynchronously<T>(
|
||||
_ closure: @escaping () -> T
|
||||
) -> T {
|
||||
|
||||
var result: T?
|
||||
self.performAndWait {
|
||||
|
||||
@@ -49,9 +53,11 @@ extension NSPersistentStoreCoordinator {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func performSynchronously<T>(_ closure: @escaping () throws -> T) throws -> T {
|
||||
|
||||
var closureError: Error?
|
||||
internal func performSynchronously<T>(
|
||||
_ closure: @escaping () throws(any Swift.Error) -> T
|
||||
) throws(CoreStoreError) -> T {
|
||||
|
||||
var closureError: (any Swift.Error)?
|
||||
var result: T?
|
||||
self.performAndWait {
|
||||
|
||||
@@ -66,29 +72,27 @@ extension NSPersistentStoreCoordinator {
|
||||
}
|
||||
if let closureError = closureError {
|
||||
|
||||
throw closureError
|
||||
throw CoreStoreError(closureError)
|
||||
}
|
||||
return result!
|
||||
}
|
||||
|
||||
|
||||
@nonobjc
|
||||
internal func addPersistentStoreSynchronously(_ storeType: String, configuration: ModelConfiguration, URL storeURL: URL?, options: [AnyHashable: Any]?) throws -> NSPersistentStore {
|
||||
|
||||
internal func addPersistentStoreSynchronously(
|
||||
_ storeType: String,
|
||||
configuration: ModelConfiguration,
|
||||
URL storeURL: URL?,
|
||||
options: [AnyHashable: Any]?
|
||||
) throws(CoreStoreError) -> NSPersistentStore {
|
||||
|
||||
return try self.performSynchronously {
|
||||
|
||||
do {
|
||||
|
||||
return try self.addPersistentStore(
|
||||
ofType: storeType,
|
||||
configurationName: configuration,
|
||||
at: storeURL,
|
||||
options: options
|
||||
)
|
||||
}
|
||||
catch {
|
||||
|
||||
throw CoreStoreError(error)
|
||||
}
|
||||
|
||||
return try self.addPersistentStore(
|
||||
ofType: storeType,
|
||||
configurationName: configuration,
|
||||
at: storeURL,
|
||||
options: options
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,12 +408,6 @@ public final class ObjectMonitor<O: DynamicObject>: Hashable, ObjectRepresentati
|
||||
inObject: observer
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,9 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Stored<V>>) -> FieldProxy<V> {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Stored<V>>
|
||||
) -> FieldProxy<V> {
|
||||
|
||||
return .init(rawObject: self.rawObject, keyPath: member)
|
||||
}
|
||||
@@ -46,7 +48,9 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Virtual<V>>) -> FieldProxy<V> {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Virtual<V>>
|
||||
) -> FieldProxy<V> {
|
||||
|
||||
return .init(rawObject: self.rawObject, keyPath: member)
|
||||
}
|
||||
@@ -54,7 +58,9 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Coded<V>>) -> FieldProxy<V> {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Coded<V>>
|
||||
) -> FieldProxy<V> {
|
||||
|
||||
return .init(rawObject: self.rawObject, keyPath: member)
|
||||
}
|
||||
@@ -111,22 +117,34 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init<OBase>(rawObject: CoreStoreManagedObject, keyPath: KeyPath<O, FieldContainer<OBase>.Stored<V>>) {
|
||||
internal init<OBase>(
|
||||
rawObject: CoreStoreManagedObject,
|
||||
keyPath: KeyPath<O, FieldContainer<OBase>.Stored<V>>
|
||||
) {
|
||||
|
||||
self.init(rawObject: rawObject, field: O.meta[keyPath: keyPath])
|
||||
}
|
||||
|
||||
internal init<OBase>(rawObject: CoreStoreManagedObject, keyPath: KeyPath<O, FieldContainer<OBase>.Virtual<V>>) {
|
||||
internal init<OBase>(
|
||||
rawObject: CoreStoreManagedObject,
|
||||
keyPath: KeyPath<O, FieldContainer<OBase>.Virtual<V>>
|
||||
) {
|
||||
|
||||
self.init(rawObject: rawObject, field: O.meta[keyPath: keyPath])
|
||||
}
|
||||
|
||||
internal init<OBase>(rawObject: CoreStoreManagedObject, keyPath: KeyPath<O, FieldContainer<OBase>.Coded<V>>) {
|
||||
internal init<OBase>(
|
||||
rawObject: CoreStoreManagedObject,
|
||||
keyPath: KeyPath<O, FieldContainer<OBase>.Coded<V>>
|
||||
) {
|
||||
|
||||
self.init(rawObject: rawObject, field: O.meta[keyPath: keyPath])
|
||||
}
|
||||
|
||||
internal init<OBase>(rawObject: CoreStoreManagedObject, field: FieldContainer<OBase>.Stored<V>) {
|
||||
internal init<OBase>(
|
||||
rawObject: CoreStoreManagedObject,
|
||||
field: FieldContainer<OBase>.Stored<V>
|
||||
) {
|
||||
|
||||
let keyPathString = field.keyPath
|
||||
self.getValue = {
|
||||
@@ -157,7 +175,10 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
}
|
||||
}
|
||||
|
||||
internal init<OBase>(rawObject: CoreStoreManagedObject, field: FieldContainer<OBase>.Virtual<V>) {
|
||||
internal init<OBase>(
|
||||
rawObject: CoreStoreManagedObject,
|
||||
field: FieldContainer<OBase>.Virtual<V>
|
||||
) {
|
||||
|
||||
let keyPathString = field.keyPath
|
||||
self.getValue = {
|
||||
@@ -190,7 +211,10 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
}
|
||||
}
|
||||
|
||||
internal init<OBase>(rawObject: CoreStoreManagedObject, field: FieldContainer<OBase>.Coded<V>) {
|
||||
internal init<OBase>(
|
||||
rawObject: CoreStoreManagedObject,
|
||||
field: FieldContainer<OBase>.Coded<V>
|
||||
) {
|
||||
|
||||
let keyPathString = field.keyPath
|
||||
self.getValue = {
|
||||
|
||||
@@ -94,8 +94,10 @@ extension ObjectPublisher.ReactiveNamespace {
|
||||
- parameter emitInitialValue: If `true`, the current value is immediately emitted to the first subscriber. If `false`, the event fires only starting the next `ObjectSnapshot` update.
|
||||
- returns: A `Publisher` that emits an `ObjectSnapshot?` whenever changes occur in the `ObjectPublisher`. The event emits `nil` if the object has been deletd.
|
||||
*/
|
||||
public func snapshot(emitInitialValue: Bool = true) -> ObjectPublisher.SnapshotPublisher {
|
||||
|
||||
public func snapshot(
|
||||
emitInitialValue: Bool = true
|
||||
) -> ObjectPublisher.SnapshotPublisher {
|
||||
|
||||
return .init(
|
||||
objectPublisher: self.base,
|
||||
emitInitialValue: emitInitialValue
|
||||
@@ -111,7 +113,9 @@ extension ObjectPublisher.ReactiveNamespace where O: NSManagedObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<V: AllowedObjectiveCKeyPathValue>(dynamicMember member: KeyPath<O, V>) -> some Publisher {
|
||||
public subscript<V: AllowedObjectiveCKeyPathValue>(
|
||||
dynamicMember member: KeyPath<O, V>
|
||||
) -> some Publisher {
|
||||
|
||||
return self
|
||||
.snapshot(emitInitialValue: true)
|
||||
@@ -127,8 +131,10 @@ extension ObjectPublisher.ReactiveNamespace where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Stored<V>>) -> some Publisher {
|
||||
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Stored<V>>
|
||||
) -> some Publisher {
|
||||
|
||||
return self
|
||||
.snapshot(emitInitialValue: true)
|
||||
.map({ $0?[dynamicMember: member] })
|
||||
@@ -137,8 +143,10 @@ extension ObjectPublisher.ReactiveNamespace where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Virtual<V>>) -> some Publisher {
|
||||
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Virtual<V>>
|
||||
) -> some Publisher {
|
||||
|
||||
return self
|
||||
.snapshot(emitInitialValue: true)
|
||||
.map({ $0?[dynamicMember: member] })
|
||||
@@ -147,8 +155,10 @@ extension ObjectPublisher.ReactiveNamespace where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Coded<V>>) -> some Publisher {
|
||||
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Coded<V>>
|
||||
) -> some Publisher {
|
||||
|
||||
return self
|
||||
.snapshot(emitInitialValue: true)
|
||||
.map({ $0?[dynamicMember: member] })
|
||||
|
||||
@@ -52,8 +52,10 @@ extension ObjectPublisher {
|
||||
public typealias Output = ObjectSnapshot<O>?
|
||||
public typealias Failure = Never
|
||||
|
||||
public func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
|
||||
|
||||
public func receive<S: Subscriber>(
|
||||
subscriber: S
|
||||
) where S.Input == Output, S.Failure == Failure {
|
||||
|
||||
subscriber.receive(
|
||||
subscription: ObjectSnapshotSubscription(
|
||||
publisher: self.objectPublisher,
|
||||
|
||||
@@ -333,15 +333,6 @@ extension ObjectPublisher where O: NSManagedObject {
|
||||
|
||||
return self.snapshot?[dynamicMember: member]
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, message: "Accessing the property directly now works")
|
||||
public func value<V: AllowedObjectiveCKeyPathValue>(forKeyPath keyPath: KeyPath<O, V>) -> V! {
|
||||
|
||||
return self[dynamicMember: keyPath]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -432,62 +423,6 @@ extension ObjectPublisher where O: CoreStoreObject {
|
||||
return V.cs_toPublishedType(from: snapshotValue, in: self.context)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, ValueContainer<OBase>.Required<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, ValueContainer<OBase>.Optional<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Required<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Optional<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToOne<D>>) -> D? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyOrdered<D>>) -> [D]? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyUnordered<D>>) -> Set<D>? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
@@ -496,3 +431,48 @@ extension ObjectPublisher where O: CoreStoreObject {
|
||||
return self.object?[keyPath: member]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension ObjectPublisher where O: CoreStoreObject {
|
||||
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, ValueContainer<OBase>.Required<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, ValueContainer<OBase>.Optional<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Required<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Optional<V>>) -> V? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToOne<D>>) -> D? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyOrdered<D>>) -> [D]? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyUnordered<D>>) -> Set<D>? {
|
||||
|
||||
return self.object?[keyPath: member].value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ import AppKit
|
||||
The `ObjectSnapshot` is a full copy of a `DynamicObject`'s properties at a given point in time. This is useful especially when keeping thread-safe state values, in ViewModels for example. Since this is a value type, any changes in this `struct` does not affect the actual object.
|
||||
*/
|
||||
@dynamicMemberLookup
|
||||
public struct ObjectSnapshot<O: DynamicObject>: ObjectRepresentation, Hashable {
|
||||
public struct ObjectSnapshot<O: DynamicObject>: ObjectRepresentation, Hashable, @unchecked Sendable {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -189,7 +189,9 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Stored<V>>) -> V {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Stored<V>>
|
||||
) -> V {
|
||||
|
||||
get {
|
||||
|
||||
@@ -206,7 +208,9 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Virtual<V>>) -> V {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Virtual<V>>
|
||||
) -> V {
|
||||
|
||||
get {
|
||||
|
||||
@@ -223,7 +227,9 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Coded<V>>) -> V {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Coded<V>>
|
||||
) -> V {
|
||||
|
||||
get {
|
||||
|
||||
@@ -240,7 +246,9 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, FieldContainer<OBase>.Relationship<V>>) -> V.PublishedType {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, FieldContainer<OBase>.Relationship<V>>
|
||||
) -> V.PublishedType {
|
||||
|
||||
get {
|
||||
|
||||
@@ -255,11 +263,19 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
self.values[key] = V.cs_toSnapshotType(from: newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, ValueContainer<OBase>.Required<V>>) -> V {
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension ObjectSnapshot where O: CoreStoreObject {
|
||||
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, ValueContainer<OBase>.Required<V>>
|
||||
) -> V {
|
||||
|
||||
get {
|
||||
|
||||
@@ -273,10 +289,9 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, ValueContainer<OBase>.Optional<V>>) -> V? {
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, ValueContainer<OBase>.Optional<V>>
|
||||
) -> V? {
|
||||
|
||||
get {
|
||||
|
||||
@@ -289,11 +304,10 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
self.values[key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Required<V>>) -> V {
|
||||
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Required<V>>
|
||||
) -> V {
|
||||
|
||||
get {
|
||||
|
||||
@@ -306,11 +320,10 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
self.values[key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, V>(dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Optional<V>>) -> V? {
|
||||
|
||||
public subscript<OBase, V>(
|
||||
dynamicMember member: KeyPath<O, TransformableContainer<OBase>.Optional<V>>
|
||||
) -> V? {
|
||||
|
||||
get {
|
||||
|
||||
@@ -323,11 +336,10 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
self.values[key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToOne<D>>) -> ObjectPublisher<D>? {
|
||||
|
||||
public subscript<OBase, D>(
|
||||
dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToOne<D>>
|
||||
) -> ObjectPublisher<D>? {
|
||||
|
||||
get {
|
||||
|
||||
@@ -344,11 +356,10 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
self.values[key] = newValue?.objectID()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyOrdered<D>>) -> [ObjectPublisher<D>] {
|
||||
|
||||
public subscript<OBase, D>(
|
||||
dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyOrdered<D>>
|
||||
) -> [ObjectPublisher<D>] {
|
||||
|
||||
get {
|
||||
|
||||
@@ -363,11 +374,10 @@ extension ObjectSnapshot where O: CoreStoreObject {
|
||||
self.values[key] = newValue.map({ $0.objectID() })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public subscript<OBase, D>(dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyUnordered<D>>) -> Set<ObjectPublisher<D>> {
|
||||
|
||||
public subscript<OBase, D>(
|
||||
dynamicMember member: KeyPath<O, RelationshipContainer<OBase>.ToManyUnordered<D>>
|
||||
) -> Set<ObjectPublisher<D>> {
|
||||
|
||||
get {
|
||||
|
||||
|
||||
47
Sources/Operators.swift
Normal file
47
Sources/Operators.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Operators.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2023 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.
|
||||
//
|
||||
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
infix operator .== : ComparisonPrecedence
|
||||
|
||||
|
||||
infix operator &&? : LogicalConjunctionPrecedence
|
||||
infix operator ||? : LogicalConjunctionPrecedence
|
||||
|
||||
|
||||
// MARK: - ~
|
||||
|
||||
/**
|
||||
Connects multiple `KeyPathStringConvertible`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = dataStack.fetchOne(
|
||||
From<Pet>().where(
|
||||
(\.master ~ \.name) == "John"
|
||||
)
|
||||
)
|
||||
```
|
||||
*/
|
||||
infix operator ~ : AdditionPrecedence
|
||||
@@ -151,7 +151,7 @@ public struct OrderBy<O: DynamicObject>: OrderByClause, FetchClause, QueryClause
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending(_ keyPath: KeyPathString) -> SortKey {
|
||||
public static func ascending(_ keyPath: KeyPathString) -> Self {
|
||||
|
||||
return SortKey(descriptor: .init(key: keyPath, ascending: true))
|
||||
}
|
||||
@@ -159,7 +159,7 @@ public struct OrderBy<O: DynamicObject>: OrderByClause, FetchClause, QueryClause
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending(_ keyPath: KeyPathString) -> SortKey {
|
||||
public static func descending(_ keyPath: KeyPathString) -> Self {
|
||||
|
||||
return SortKey(descriptor: .init(key: keyPath, ascending: false))
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public struct OrderBy<O: DynamicObject>: OrderByClause, FetchClause, QueryClause
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<T>(_ keyPath: KeyPath<O, T>) -> SortKey where O: NSManagedObject {
|
||||
public static func ascending<T>(_ keyPath: KeyPath<O, T>) -> Self where O: NSManagedObject {
|
||||
|
||||
return .ascending(keyPath._kvcKeyPathString!)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ public struct OrderBy<O: DynamicObject>: OrderByClause, FetchClause, QueryClause
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<T>(_ keyPath: KeyPath<O, T>) -> SortKey where O: NSManagedObject {
|
||||
public static func descending<T>(_ keyPath: KeyPath<O, T>) -> Self where O: NSManagedObject {
|
||||
|
||||
return .descending(keyPath._kvcKeyPathString!)
|
||||
}
|
||||
@@ -189,94 +189,24 @@ public struct OrderBy<O: DynamicObject>: OrderByClause, FetchClause, QueryClause
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, FieldContainer<O>.Stored<T>>) -> SortKey {
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, FieldContainer<O>.Stored<T>>) -> Self {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Required<T>>) -> SortKey {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Optional<T>>) -> SortKey {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Required<T>>) -> SortKey {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Optional<T>>) -> SortKey {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<T>(_ attribute: KeyPath<O, FieldContainer<O>.Stored<T>>) -> SortKey {
|
||||
public static func descending<T>(_ attribute: KeyPath<O, FieldContainer<O>.Stored<T>>) -> Self {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Required<T>>) -> SortKey {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Optional<T>>) -> SortKey {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Required<T>>) -> SortKey {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Optional<T>>) -> SortKey {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
fileprivate let descriptor: NSSortDescriptor
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "O")
|
||||
public typealias D = O
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +217,7 @@ extension OrderBy.SortKey where O: CoreStoreObject {
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in ascending order
|
||||
*/
|
||||
public static func ascending<K: KeyPathStringConvertible>(_ attribute: (O) -> K) -> OrderBy<O>.SortKey {
|
||||
public static func ascending<K: KeyPathStringConvertible>(_ attribute: (O) -> K) -> Self {
|
||||
|
||||
return .ascending(attribute(O.meta).cs_keyPathString)
|
||||
}
|
||||
@@ -295,7 +225,7 @@ extension OrderBy.SortKey where O: CoreStoreObject {
|
||||
/**
|
||||
Indicates that the `KeyPathString` should be sorted in descending order
|
||||
*/
|
||||
public static func descending<K: KeyPathStringConvertible>(_ attribute: (O) -> K) -> OrderBy<O>.SortKey {
|
||||
public static func descending<K: KeyPathStringConvertible>(_ attribute: (O) -> K) -> Self {
|
||||
|
||||
return .descending(attribute(O.meta).cs_keyPathString)
|
||||
}
|
||||
@@ -333,3 +263,52 @@ extension Sequence where Iterator.Element: OrderByClause {
|
||||
return OrderBy(self.flatMap({ $0.sortDescriptors }))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Deprecated
|
||||
|
||||
@available(*, deprecated, message: """
|
||||
Legacy `Value.*`, `Transformable.*`, and `Relationship.*` declarations will soon be obsoleted. Please migrate your models and stores to new models that use `@Field.*` property wrappers. See: https://github.com/JohnEstropia/CoreStore?tab=readme-ov-file#new-field-property-wrapper-syntax
|
||||
""")
|
||||
extension OrderBy.SortKey where O: CoreStoreObject {
|
||||
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Required<T>>) -> Self {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Optional<T>>) -> Self {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Required<T>>) -> Self {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func ascending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Optional<T>>) -> Self {
|
||||
|
||||
return .ascending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func descending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Required<T>>) -> Self {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func descending<T>(_ attribute: KeyPath<O, ValueContainer<O>.Optional<T>>) -> Self {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func descending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Required<T>>) -> Self {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
|
||||
public static func descending<T>(_ attribute: KeyPath<O, TransformableContainer<O>.Optional<T>>) -> Self {
|
||||
|
||||
return .descending(O.meta[keyPath: attribute].keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user