mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-12 12:20:30 +01:00
Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3816b9abf | ||
|
|
21961780d4 | ||
|
|
305e2b61a0 | ||
|
|
588fa35c84 | ||
|
|
f6614cda66 | ||
|
|
639574d8c2 | ||
|
|
27ffc1d225 | ||
|
|
ba6f0c39d5 | ||
|
|
ab2eac8f6c | ||
|
|
f460a0b30f | ||
|
|
50bc3ace06 | ||
|
|
d2ddf2002f | ||
|
|
b4117eeb02 | ||
|
|
50e50c0613 | ||
|
|
5c8a0e425b | ||
|
|
03b71caf7e | ||
|
|
7ff29d6086 | ||
|
|
8d86425875 | ||
|
|
0aa8c03424 | ||
|
|
85706a3c57 | ||
|
|
c5ae4606b9 | ||
|
|
fa682215c5 | ||
|
|
be5da632b3 | ||
|
|
dc73cd6dd9 | ||
|
|
53100b202d | ||
|
|
2a62770552 | ||
|
|
f436b26e8e | ||
|
|
0b57cff27d | ||
|
|
3ebc44b546 | ||
|
|
68f1027ba7 | ||
|
|
8bac4aa901 | ||
|
|
211e69023e | ||
|
|
2912dcf010 | ||
|
|
3e00a3da06 | ||
|
|
9922deac4d | ||
|
|
86be046c9f | ||
|
|
0f10bc3349 | ||
|
|
9685f0aef2 | ||
|
|
3bd459bb1a | ||
|
|
28b43f33fa | ||
|
|
74c64619c3 | ||
|
|
f36cb8af63 | ||
|
|
10ccadd96c | ||
|
|
5c0e78bd53 | ||
|
|
8a09688117 | ||
|
|
a366bcf1a3 | ||
|
|
c6e68ac24f | ||
|
|
a20ad87583 | ||
|
|
a11915db12 | ||
|
|
961f39a806 | ||
|
|
3096cb784c | ||
|
|
809aa4ff96 | ||
|
|
8d926d25ec | ||
|
|
790454f514 | ||
|
|
fb7e2f7f7f | ||
|
|
f72efc80b2 | ||
|
|
fd3a9b00ec | ||
|
|
5f5000218a | ||
|
|
e8eb309d82 | ||
|
|
d0c3203e63 | ||
|
|
f5b3901caa | ||
|
|
1a99fea820 | ||
|
|
195b60615b | ||
|
|
2c394965b8 | ||
|
|
746d697691 | ||
|
|
5689158b43 | ||
|
|
6fcdf3d011 | ||
|
|
e26573c18e | ||
|
|
801cf8d9f0 | ||
|
|
6a42a0054e | ||
|
|
8c437e19b8 | ||
|
|
9cd3b6c879 | ||
|
|
fe135acbec | ||
|
|
997c5bdcfa | ||
|
|
23e12c4539 | ||
|
|
f618617053 | ||
|
|
49b8b9c372 | ||
|
|
129f975d96 | ||
|
|
a2e463e58c | ||
|
|
5fd50f0e15 | ||
|
|
7f9a915d71 | ||
|
|
0a81736b7a | ||
|
|
f9b6dd0c6a | ||
|
|
0354401b56 | ||
|
|
0304067beb | ||
|
|
ddd83da434 | ||
|
|
fc7df671de | ||
|
|
5fde9030c7 | ||
|
|
d7b07b3f00 | ||
|
|
ddd1ffb29f | ||
|
|
98094000bb | ||
|
|
d5026ef996 | ||
|
|
2cd913b9dd | ||
|
|
ad9520abbc | ||
|
|
c0fc57d10c | ||
|
|
0cf4d303e4 | ||
|
|
6de397958a | ||
|
|
55292a84dc | ||
|
|
981b560d53 | ||
|
|
c4c4dd55cd | ||
|
|
1ddbe20c86 | ||
|
|
da9e8c1550 |
2
.cocoapods.yml
Normal file
2
.cocoapods.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
try:
|
||||
project: 'CoreStore.xcworkspace'
|
||||
@@ -1 +1 @@
|
||||
3.1
|
||||
3.2
|
||||
|
||||
39
.travis.yml
39
.travis.yml
@@ -1,5 +1,5 @@
|
||||
language: objective-c
|
||||
osx_image: xcode8.3
|
||||
osx_image: xcode9
|
||||
sudo: false
|
||||
git:
|
||||
submodules: false
|
||||
@@ -9,25 +9,30 @@ env:
|
||||
global:
|
||||
- LC_CTYPE=en_US.UTF-8
|
||||
- LANG=en_US.UTF-8
|
||||
matrix:
|
||||
- DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
matrix:
|
||||
- DESTINATION="OS=11.0,name=iPhone 8" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.13 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=4.0,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=11.0,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||
before_install:
|
||||
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
|
||||
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
|
||||
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.20.1/Carthage.pkg"
|
||||
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.26.0/Carthage.pkg"
|
||||
- sudo installer -pkg "Carthage.pkg" -target /
|
||||
- rm "Carthage.pkg"
|
||||
- npm install ios-sim -g
|
||||
- ios-sim start --devicetypeid "com.apple.CoreSimulator.SimDeviceType.iPhone-8, 11.0"
|
||||
before_script:
|
||||
- carthage update --use-submodules
|
||||
script:
|
||||
@@ -38,8 +43,8 @@ script:
|
||||
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
fi
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
|
||||
- if [ $POD_LINT == "YES" ]; then
|
||||
pod lib lint --quick;
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CoreStore"
|
||||
s.version = "4.0.0"
|
||||
s.version = "4.2.2"
|
||||
s.license = "MIT"
|
||||
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
|
||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||
|
||||
@@ -238,6 +238,14 @@
|
||||
B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
|
||||
B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
|
||||
B538BA7A1D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
|
||||
B53B275F1EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
|
||||
B53CA9A21EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
|
||||
B53CA9A31EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
|
||||
B53CA9A41EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
|
||||
B53CA9A51EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
|
||||
B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
@@ -441,6 +449,18 @@
|
||||
B580857A1CDF808C004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
|
||||
B580857B1CDF808D004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
|
||||
B580857C1CDF808F004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
|
||||
B5831B701F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
|
||||
B5831B711F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
|
||||
B5831B721F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
|
||||
B5831B731F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
|
||||
B5831B751F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
|
||||
B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
|
||||
B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
|
||||
B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
|
||||
B5831B7A1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
|
||||
B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
|
||||
B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
|
||||
B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
|
||||
B58B22F51C93C1BA00521925 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A53019C5C6DA005002A5 /* CoreStore.framework */; };
|
||||
B58D0C631EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */; };
|
||||
B58D0C641EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */; };
|
||||
@@ -752,6 +772,8 @@
|
||||
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; };
|
||||
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; };
|
||||
B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; };
|
||||
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreManagedObject.swift; sourceTree = "<group>"; };
|
||||
B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartialObject.swift; sourceTree = "<group>"; };
|
||||
B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationResult.swift; sourceTree = "<group>"; };
|
||||
B53FBA031CAB300C00F0D40A /* CSMigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationType.swift; sourceTree = "<group>"; };
|
||||
B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Migrating.swift"; sourceTree = "<group>"; };
|
||||
@@ -806,6 +828,9 @@
|
||||
B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestDataTestCase.swift; sourceTree = "<group>"; };
|
||||
B57D27C11D0BC20100539C58 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = "<group>"; };
|
||||
B58085741CDF7F00004C2EEB /* SetupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetupTests.swift; sourceTree = "<group>"; };
|
||||
B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributeProtocol.swift; sourceTree = "<group>"; };
|
||||
B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipProtocol.swift; sourceTree = "<group>"; };
|
||||
B5831B791F34ACBA00A9F647 /* Transformable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transformable.swift; sourceTree = "<group>"; };
|
||||
B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+DynamicModel.swift"; sourceTree = "<group>"; };
|
||||
B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvenienceTests.swift; sourceTree = "<group>"; };
|
||||
B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchableSource.swift; sourceTree = "<group>"; };
|
||||
@@ -823,6 +848,7 @@
|
||||
B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; };
|
||||
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreFetchedResultsController.swift; sourceTree = "<group>"; };
|
||||
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreError.swift; sourceTree = "<group>"; };
|
||||
B5D2D5A91F7558CB00A4DE67 /* .cocoapods.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .cocoapods.yml; sourceTree = SOURCE_ROOT; };
|
||||
B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicModelTests.swift; sourceTree = "<group>"; };
|
||||
B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreObject.swift; sourceTree = "<group>"; };
|
||||
B5D339DC1E9489C700C880DE /* DynamicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicObject.swift; sourceTree = "<group>"; };
|
||||
@@ -1019,6 +1045,7 @@
|
||||
B5E84ED91AFF82360064E85B /* LICENSE */,
|
||||
B5D9C8F61B160ED200E64F0E /* CoreStore.podspec */,
|
||||
B5BDC91A1C202269008147CD /* Cartfile */,
|
||||
B5D2D5A91F7558CB00A4DE67 /* .cocoapods.yml */,
|
||||
B5BDC9271C2024F2008147CD /* .travis.yml */,
|
||||
B5AD60CD1C90141E00F2B2E8 /* Package.swift */,
|
||||
);
|
||||
@@ -1224,17 +1251,27 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */,
|
||||
B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */,
|
||||
B5831B6E1F3355C300A9F647 /* Properties */,
|
||||
B52F74391E9B8724005F3DAC /* Dynamic Schema */,
|
||||
B5D339DC1E9489C700C880DE /* DynamicObject.swift */,
|
||||
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */,
|
||||
B5D339E61E9493A500C880DE /* Entity.swift */,
|
||||
B5D33A001E96012400C880DE /* Relationship.swift */,
|
||||
B5D339E11E948C3600C880DE /* Value.swift */,
|
||||
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */,
|
||||
);
|
||||
name = "Dynamic Models";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5831B6E1F3355C300A9F647 /* Properties */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5D33A001E96012400C880DE /* Relationship.swift */,
|
||||
B5D339E11E948C3600C880DE /* Value.swift */,
|
||||
B5831B791F34ACBA00A9F647 /* Transformable.swift */,
|
||||
);
|
||||
name = Properties;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5A5F26B1CAFF8D0004AB9AF /* Swift */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1423,18 +1460,21 @@
|
||||
B5E84F291AFF849C0064E85B /* Internal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */,
|
||||
B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */,
|
||||
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */,
|
||||
B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */,
|
||||
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
|
||||
B56923C31EB823B4007C4DC9 /* NSEntityDescription+Migration.swift */,
|
||||
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */,
|
||||
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */,
|
||||
B51260921E9B28F100402229 /* EntityIdentifier.swift */,
|
||||
B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */,
|
||||
B5E834BA1B7691F3001D3D50 /* Functions.swift */,
|
||||
B5FAD6AB1B51285300714891 /* MigrationManager.swift */,
|
||||
B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */,
|
||||
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */,
|
||||
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */,
|
||||
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
|
||||
B56923C31EB823B4007C4DC9 /* NSEntityDescription+Migration.swift */,
|
||||
B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */,
|
||||
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */,
|
||||
B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */,
|
||||
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */,
|
||||
B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */,
|
||||
@@ -1802,6 +1842,7 @@
|
||||
B5ECDC1D1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
|
||||
B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B53FBA121CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5831B751F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
|
||||
B5E1B5A81CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */,
|
||||
@@ -1820,6 +1861,7 @@
|
||||
B5FAD6AE1B518DCB00714891 /* CoreStore+Migration.swift in Sources */,
|
||||
B5E84EE71AFF84610064E85B /* CoreStore+Logging.swift in Sources */,
|
||||
B546F9731C9C553300D5AC55 /* SetupResult.swift in Sources */,
|
||||
B53CA9A21EF1EF1600E0F440 /* PartialObject.swift in Sources */,
|
||||
B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */,
|
||||
B5E84F111AFF847B0064E85B /* Select.swift in Sources */,
|
||||
B51260931E9B28F100402229 /* EntityIdentifier.swift in Sources */,
|
||||
@@ -1875,6 +1917,7 @@
|
||||
B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
|
||||
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
|
||||
B56923E81EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B275F1EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A011E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */,
|
||||
B56923C91EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -1892,6 +1935,7 @@
|
||||
B59FA0AE1CCBAC95007C9BCA /* ICloudStore.swift in Sources */,
|
||||
B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */,
|
||||
B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
B5831B7A1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
B546F9691C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B53FBA1E1CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */,
|
||||
B549F65E1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
@@ -1907,6 +1951,7 @@
|
||||
B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */,
|
||||
B53FBA041CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
|
||||
B5E84EF41AFF846E0064E85B /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B5831B701F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
|
||||
B5DBE2CD1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
|
||||
B546F95D1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B5D339E71E9493A500C880DE /* Entity.swift in Sources */,
|
||||
@@ -1986,6 +2031,7 @@
|
||||
B5ECDC1F1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
|
||||
B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
|
||||
B5E1B5AA1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B5D339F21E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B5D3F6461C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
|
||||
@@ -2004,6 +2050,7 @@
|
||||
82BA18A31C4BBD2200A0916E /* DataStack.swift in Sources */,
|
||||
82BA18C81C4BBD5900A0916E /* MigrationChain.swift in Sources */,
|
||||
B546F9741C9C553300D5AC55 /* SetupResult.swift in Sources */,
|
||||
B53CA9A31EF1EF1600E0F440 /* PartialObject.swift in Sources */,
|
||||
82BA18B11C4BBD3100A0916E /* SaveResult.swift in Sources */,
|
||||
82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */,
|
||||
B51260941E9B28F100402229 /* EntityIdentifier.swift in Sources */,
|
||||
@@ -2059,6 +2106,7 @@
|
||||
82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */,
|
||||
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */,
|
||||
B56923E91EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A021E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B559CD4B1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
|
||||
B56923CA1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -2076,6 +2124,7 @@
|
||||
82BA18D31C4BBD7100A0916E /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
82BA18AD1C4BBD3100A0916E /* UnsafeDataTransaction.swift in Sources */,
|
||||
B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
B53FBA201CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */,
|
||||
82BA18A81C4BBD2900A0916E /* CoreStoreLogger.swift in Sources */,
|
||||
B549F65F1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
@@ -2091,6 +2140,7 @@
|
||||
B53FBA061CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
|
||||
82BA18BE1C4BBD4A00A0916E /* Tweak.swift in Sources */,
|
||||
B5DBE2CE1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
|
||||
B5831B711F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
|
||||
B546F95E1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B5ECDC0D1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
|
||||
B5D339E81E9493A500C880DE /* Entity.swift in Sources */,
|
||||
@@ -2170,6 +2220,7 @@
|
||||
B5D3F6481C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
|
||||
B5220E1C1D130801009BC71E /* FetchedResultsControllerDelegate.swift in Sources */,
|
||||
B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
|
||||
B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */,
|
||||
B5D339F41E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B5220E241D13085E009BC71E /* NSFetchedResultsController+Convenience.swift in Sources */,
|
||||
@@ -2188,6 +2239,7 @@
|
||||
B52DD1961BE1F92500949AFE /* DataStack.swift in Sources */,
|
||||
B5ECDBFD1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
|
||||
B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */,
|
||||
B53CA9A51EF1EF1600E0F440 /* PartialObject.swift in Sources */,
|
||||
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */,
|
||||
B53FBA1C1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */,
|
||||
B51260961E9B28F100402229 /* EntityIdentifier.swift in Sources */,
|
||||
@@ -2243,6 +2295,7 @@
|
||||
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */,
|
||||
B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B56923EB1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A041E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
B56923CC1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -2260,6 +2313,7 @@
|
||||
B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */,
|
||||
B5ECDC331CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */,
|
||||
B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */,
|
||||
B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
B5220E151D130663009BC71E /* CoreStore+Observing.swift in Sources */,
|
||||
B549F6611E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
@@ -2275,6 +2329,7 @@
|
||||
B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */,
|
||||
B5519A5C1CA2008C002BEF78 /* CSBaseDataTransaction.swift in Sources */,
|
||||
B5DBE2D51C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
|
||||
B5831B731F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
|
||||
B5AEFAB81C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
|
||||
B598514B1C90289F00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */,
|
||||
B5D339EA1E9493A500C880DE /* Entity.swift in Sources */,
|
||||
@@ -2354,6 +2409,7 @@
|
||||
B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
|
||||
B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
|
||||
B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
|
||||
B5D3F6471C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
|
||||
B5D339F31E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
|
||||
B5E1B5A01CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */,
|
||||
@@ -2372,6 +2428,7 @@
|
||||
B56321A81BD65219006C9394 /* NSManagedObject+Convenience.swift in Sources */,
|
||||
B546F9751C9C553300D5AC55 /* SetupResult.swift in Sources */,
|
||||
B56321981BD65216006C9394 /* Where.swift in Sources */,
|
||||
B53CA9A41EF1EF1600E0F440 /* PartialObject.swift in Sources */,
|
||||
B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */,
|
||||
B5FE4DA91C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
|
||||
B51260951E9B28F100402229 /* EntityIdentifier.swift in Sources */,
|
||||
@@ -2427,6 +2484,7 @@
|
||||
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
|
||||
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */,
|
||||
B56923EA1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
|
||||
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
|
||||
B5D33A031E96012400C880DE /* Relationship.swift in Sources */,
|
||||
B559CD4C1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
|
||||
B56923CB1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
|
||||
@@ -2444,6 +2502,7 @@
|
||||
B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */,
|
||||
B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
|
||||
B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */,
|
||||
B53FBA211CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */,
|
||||
B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */,
|
||||
B549F6601E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
@@ -2459,6 +2518,7 @@
|
||||
B53FBA071CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
|
||||
B56321841BD65216006C9394 /* DefaultLogger.swift in Sources */,
|
||||
B5DBE2CF1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
|
||||
B5831B721F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
|
||||
B546F95F1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
|
||||
B5ECDC0E1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
|
||||
B5D339E91E9493A500C880DE /* Entity.swift in Sources */,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
import CoreStore
|
||||
|
||||
// MARK: - AppDelegate
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12113" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12078"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
@@ -459,8 +459,8 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
|
||||
<rect key="frame" x="20" y="69.5" width="552" height="36.5"/>
|
||||
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
|
||||
<rect key="frame" x="16" y="89.5" width="343" height="50"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
|
||||
@@ -511,8 +511,8 @@
|
||||
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
|
||||
<rect key="frame" x="20" y="49" width="552" height="20.5"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
|
||||
<rect key="frame" x="16" y="69" width="343" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -797,8 +797,8 @@
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="536"/>
|
||||
<mapView verifyAmbiguity="ignoreSizes" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="558"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
|
||||
</connections>
|
||||
@@ -806,7 +806,7 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="RZg-hi-T8O" firstAttribute="top" secondItem="V2U-0R-Ts0" secondAttribute="bottom" id="GcS-Jz-Wcm"/>
|
||||
<constraint firstItem="RZg-hi-T8O" firstAttribute="top" secondItem="V2U-0R-Ts0" secondAttribute="bottom" id="N9r-9J-68d"/>
|
||||
<constraint firstItem="V2U-0R-Ts0" firstAttribute="top" secondItem="k4s-iL-Krh" secondAttribute="top" id="S5Z-Da-V6J"/>
|
||||
<constraint firstAttribute="trailing" secondItem="V2U-0R-Ts0" secondAttribute="trailing" id="YPc-RK-5ib"/>
|
||||
<constraint firstItem="V2U-0R-Ts0" firstAttribute="leading" secondItem="k4s-iL-Krh" secondAttribute="leading" id="hk5-Rz-FyU"/>
|
||||
@@ -820,7 +820,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="YnG-TD-zxQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3694" y="2020"/>
|
||||
<point key="canvasLocation" x="3693.5" y="2019.5"/>
|
||||
</scene>
|
||||
<!--Logger-->
|
||||
<scene sceneID="n7W-0g-bbY">
|
||||
@@ -927,7 +927,7 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="YVj-dA-fyV">
|
||||
<rect key="frame" x="20" y="26" width="560" height="29"/>
|
||||
<rect key="frame" x="20" y="26" width="335" height="29"/>
|
||||
<segments>
|
||||
<segment title="Fetch"/>
|
||||
<segment title="Query"/>
|
||||
|
||||
@@ -1,36 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10169.1" systemVersion="15D21" minimumToolsVersion="Automatic">
|
||||
<entity name="Palette" representedClassName="CoreStoreDemo.Palette">
|
||||
<attribute name="brightness" optional="YES" attributeType="Float" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="colorName" optional="YES" transient="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="hue" optional="YES" attributeType="Integer 32" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="saturation" optional="YES" attributeType="Float" defaultValueString="0.0" syncable="YES"/>
|
||||
<userInfo/>
|
||||
</entity>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16F73" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Place" representedClassName="CoreStoreDemo.Place" syncable="YES">
|
||||
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="subtitle" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="TimeZone" representedClassName="CoreStoreDemo.TimeZone" syncable="YES">
|
||||
<attribute name="abbreviation" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||
</entity>
|
||||
<configuration name="FetchingAndQueryingDemo">
|
||||
<memberEntity name="TimeZone"/>
|
||||
</configuration>
|
||||
<configuration name="ObservingDemo">
|
||||
<memberEntity name="Palette"/>
|
||||
</configuration>
|
||||
<configuration name="TransactionsDemo">
|
||||
<memberEntity name="Place"/>
|
||||
</configuration>
|
||||
<elements>
|
||||
<element name="Palette" positionX="261" positionY="189" width="128" height="105"/>
|
||||
<element name="Place" positionX="261" positionY="225" width="128" height="105"/>
|
||||
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
|
||||
</elements>
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.1</string>
|
||||
<string>4.0.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<string>4</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
import CoreStore
|
||||
|
||||
|
||||
private struct Static {
|
||||
struct ColorsDemo {
|
||||
|
||||
enum Filter: String {
|
||||
|
||||
@@ -33,8 +33,8 @@ private struct Static {
|
||||
switch self {
|
||||
|
||||
case .all: return Where(true)
|
||||
case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9)
|
||||
case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4)
|
||||
case .light: return Palette.where({ $0.brightness >= 0.9 })
|
||||
case .dark: return Palette.where({ $0.brightness <= 0.4 })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,25 +45,38 @@ private struct Static {
|
||||
|
||||
self.palettes.refetch(
|
||||
self.filter.whereClause(),
|
||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
||||
Palette.orderBy(ascending: { $0.hue })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
static let stack: DataStack = {
|
||||
|
||||
return DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "ColorsDemo",
|
||||
entities: [
|
||||
Entity<Palette>("Palette"),
|
||||
],
|
||||
versionLock: [
|
||||
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
|
||||
]
|
||||
)
|
||||
)
|
||||
}()
|
||||
|
||||
static let palettes: ListMonitor<Palette> = {
|
||||
|
||||
try! CoreStore.addStorageAndWait(
|
||||
try! ColorsDemo.stack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "ColorsDemo.sqlite",
|
||||
configuration: "ObservingDemo",
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
)
|
||||
|
||||
return CoreStore.monitorSectionedList(
|
||||
return ColorsDemo.stack.monitorSectionedList(
|
||||
From<Palette>(),
|
||||
SectionBy(#keyPath(Palette.colorName)),
|
||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
||||
SectionBy(Palette.keyPath({ $0.colorName })),
|
||||
Palette.orderBy(ascending: { $0.hue })
|
||||
)
|
||||
}()
|
||||
}
|
||||
@@ -77,7 +90,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
deinit {
|
||||
|
||||
Static.palettes.removeObserver(self)
|
||||
ColorsDemo.palettes.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +111,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
]
|
||||
|
||||
let filterBarButton = UIBarButtonItem(
|
||||
title: Static.filter.rawValue,
|
||||
title: ColorsDemo.filter.rawValue,
|
||||
style: .plain,
|
||||
target: self,
|
||||
action: #selector(self.filterBarButtonItemTouched(_:))
|
||||
@@ -113,9 +126,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
]
|
||||
self.filterBarButton = filterBarButton
|
||||
|
||||
Static.palettes.addObserver(self)
|
||||
ColorsDemo.palettes.addObserver(self)
|
||||
|
||||
self.setTable(enabled: !Static.palettes.isPendingRefetch)
|
||||
self.setTable(enabled: !ColorsDemo.palettes.isPendingRefetch)
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
@@ -137,19 +150,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
|
||||
return Static.palettes.numberOfSections()
|
||||
return ColorsDemo.palettes.numberOfSections()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
return Static.palettes.numberOfObjectsInSection(section)
|
||||
return ColorsDemo.palettes.numberOfObjectsInSection(section)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
|
||||
|
||||
let palette = Static.palettes[indexPath]
|
||||
let palette = ColorsDemo.palettes[indexPath]
|
||||
cell.colorView?.backgroundColor = palette.color
|
||||
cell.label?.text = palette.colorText
|
||||
|
||||
@@ -165,7 +178,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
self.performSegue(
|
||||
withIdentifier: "ObjectObserverDemoViewController",
|
||||
sender: Static.palettes[indexPath]
|
||||
sender: ColorsDemo.palettes[indexPath]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -174,8 +187,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
switch editingStyle {
|
||||
|
||||
case .delete:
|
||||
let palette = Static.palettes[indexPath]
|
||||
CoreStore.perform(
|
||||
let palette = ColorsDemo.palettes[indexPath]
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
transaction.delete(palette)
|
||||
@@ -190,7 +203,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
|
||||
return Static.palettes.sectionInfoAtIndex(section).name
|
||||
return ColorsDemo.palettes.sectionInfoAtIndex(section).name
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +226,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
|
||||
|
||||
self.filterBarButton?.title = Static.filter.rawValue
|
||||
self.filterBarButton?.title = ColorsDemo.filter.rawValue
|
||||
self.tableView.reloadData()
|
||||
self.setTable(enabled: true)
|
||||
}
|
||||
@@ -235,7 +248,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell {
|
||||
|
||||
let palette = Static.palettes[indexPath]
|
||||
let palette = ColorsDemo.palettes[indexPath]
|
||||
cell.colorView?.backgroundColor = palette.color
|
||||
cell.label?.text = palette.colorText
|
||||
}
|
||||
@@ -268,7 +281,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
transaction.deleteAll(From<Palette>())
|
||||
@@ -279,16 +292,16 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
Static.filter = Static.filter.next()
|
||||
ColorsDemo.filter = ColorsDemo.filter.next()
|
||||
}
|
||||
|
||||
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let palette = transaction.create(Into<Palette>())
|
||||
palette.setInitialValues()
|
||||
palette.setInitialValues(in: transaction)
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
if let palette = newValue {
|
||||
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -50,22 +50,22 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
|
||||
if let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue)))) {
|
||||
if let palette = ColorsDemo.stack.fetchOne(From<Palette>(), Palette.orderBy(ascending: { $0.hue })) {
|
||||
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||
}
|
||||
else {
|
||||
|
||||
_ = try? CoreStore.perform(
|
||||
_ = try? ColorsDemo.stack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let palette = transaction.create(Into(Palette.self))
|
||||
palette.setInitialValues()
|
||||
let palette = transaction.create(Into<Palette>())
|
||||
palette.setInitialValues(in: transaction)
|
||||
}
|
||||
)
|
||||
|
||||
let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue))))!
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
let palette = ColorsDemo.stack.fetchOne(From<Palette>(), Palette.orderBy(ascending: { $0.hue }))!
|
||||
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||
}
|
||||
|
||||
super.init(coder: aDecoder)
|
||||
@@ -85,7 +85,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
// MARK: ObjectObserver
|
||||
|
||||
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPath>) {
|
||||
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<RawKeyPath>) {
|
||||
|
||||
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
|
||||
}
|
||||
@@ -121,12 +121,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let hue = self.hueSlider?.value ?? 0
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.hue = Int32(hue)
|
||||
palette.hue .= Int(hue)
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
@@ -136,12 +136,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let saturation = self.saturationSlider?.value ?? 0
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.saturation = saturation
|
||||
palette.saturation .= saturation
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
@@ -151,12 +151,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let brightness = self.brightnessSlider?.value ?? 0
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.brightness = brightness
|
||||
palette.brightness .= brightness
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
@@ -165,7 +165,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.perform(
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
transaction.delete(self?.monitor?.object)
|
||||
@@ -176,7 +176,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
|
||||
|
||||
self.colorNameLabel?.text = palette.colorName
|
||||
self.colorNameLabel?.text = palette.colorName.value
|
||||
|
||||
let color = palette.color
|
||||
self.colorNameLabel?.textColor = color
|
||||
@@ -184,17 +184,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
self.hsbLabel?.text = palette.colorText
|
||||
|
||||
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.hue)) == true {
|
||||
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.hue }) == true {
|
||||
|
||||
self.hueSlider?.value = Float(palette.hue)
|
||||
self.hueSlider?.value = Float(palette.hue.value)
|
||||
}
|
||||
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.saturation)) == true {
|
||||
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.saturation }) == true {
|
||||
|
||||
self.saturationSlider?.value = palette.saturation
|
||||
self.saturationSlider?.value = palette.saturation.value
|
||||
}
|
||||
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.brightness)) == true {
|
||||
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.brightness }) == true {
|
||||
|
||||
self.brightnessSlider?.value = palette.brightness
|
||||
self.brightnessSlider?.value = palette.brightness.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,64 +14,65 @@ import CoreStore
|
||||
|
||||
// MARK: - Palette
|
||||
|
||||
class Palette: NSManagedObject {
|
||||
|
||||
@NSManaged var hue: Int32
|
||||
@NSManaged var saturation: Float
|
||||
@NSManaged var brightness: Float
|
||||
final class Palette: CoreStoreObject {
|
||||
|
||||
@objc dynamic var colorName: String {
|
||||
let hue = Value.Required<Int>("hue", initial: 0)
|
||||
let saturation = Value.Required<Float>("saturation", initial: 0)
|
||||
let brightness = Value.Required<Float>("brightness", initial: 0)
|
||||
|
||||
let colorName = Value.Optional<String>(
|
||||
"colorName",
|
||||
isTransient: true,
|
||||
customGetter: Palette.getColorName
|
||||
)
|
||||
|
||||
private static func getColorName(_ partialObject: PartialObject<Palette>) -> String? {
|
||||
|
||||
get {
|
||||
if let colorName = partialObject.primitiveValue(for: { $0.colorName }) {
|
||||
|
||||
let KVCKey = #keyPath(Palette.colorName)
|
||||
if let colorName = self.getValue(forKvcKey: KVCKey) as? String {
|
||||
|
||||
return colorName
|
||||
}
|
||||
|
||||
let colorName: String
|
||||
switch self.hue % 360 {
|
||||
|
||||
case 0 ..< 20: colorName = "Lower Reds"
|
||||
case 20 ..< 57: colorName = "Oranges and Browns"
|
||||
case 57 ..< 90: colorName = "Yellow-Greens"
|
||||
case 90 ..< 159: colorName = "Greens"
|
||||
case 159 ..< 197: colorName = "Blue-Greens"
|
||||
case 197 ..< 241: colorName = "Blues"
|
||||
case 241 ..< 297: colorName = "Violets"
|
||||
case 297 ..< 331: colorName = "Magentas"
|
||||
default: colorName = "Upper Reds"
|
||||
}
|
||||
|
||||
self.setPrimitiveValue(colorName, forKey: KVCKey)
|
||||
return colorName
|
||||
}
|
||||
set {
|
||||
|
||||
let colorName: String
|
||||
switch partialObject.value(for: { $0.hue }) % 360 {
|
||||
|
||||
self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName))
|
||||
case 0 ..< 20: colorName = "Lower Reds"
|
||||
case 20 ..< 57: colorName = "Oranges and Browns"
|
||||
case 57 ..< 90: colorName = "Yellow-Greens"
|
||||
case 90 ..< 159: colorName = "Greens"
|
||||
case 159 ..< 197: colorName = "Blue-Greens"
|
||||
case 197 ..< 241: colorName = "Blues"
|
||||
case 241 ..< 297: colorName = "Violets"
|
||||
case 297 ..< 331: colorName = "Magentas"
|
||||
default: colorName = "Upper Reds"
|
||||
}
|
||||
|
||||
partialObject.setPrimitiveValue(colorName, for: { $0.colorName })
|
||||
return colorName
|
||||
}
|
||||
}
|
||||
|
||||
extension Palette {
|
||||
|
||||
var color: UIColor {
|
||||
|
||||
return UIColor(
|
||||
hue: CGFloat(self.hue) / 360.0,
|
||||
saturation: CGFloat(self.saturation),
|
||||
brightness: CGFloat(self.brightness),
|
||||
hue: CGFloat(self.hue.value) / 360.0,
|
||||
saturation: CGFloat(self.saturation.value),
|
||||
brightness: CGFloat(self.brightness.value),
|
||||
alpha: 1.0
|
||||
)
|
||||
}
|
||||
|
||||
var colorText: String {
|
||||
|
||||
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
|
||||
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%"
|
||||
}
|
||||
|
||||
func setInitialValues() {
|
||||
func setInitialValues(in transaction: BaseDataTransaction) {
|
||||
|
||||
self.hue = Int32(arc4random_uniform(360))
|
||||
self.saturation = 1.0
|
||||
self.brightness = Float(arc4random_uniform(70) + 30) / 100.0
|
||||
self.hue .= Int(arc4random_uniform(360))
|
||||
self.saturation .= Float(1.0)
|
||||
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
case 2?:
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
|
||||
_ = self.dataStack.fetchOne(From<Palette>())
|
||||
_ = self.dataStack.fetchOne(From<Place>())
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -46,7 +46,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
|
||||
|
||||
let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) {
|
||||
let modelMetadata = withExtendedLifetime(DataStack(xcodeModelName: "MigrationDemo")) {
|
||||
(dataStack: DataStack) -> ModelMetadata in
|
||||
|
||||
let models = self.models
|
||||
@@ -91,6 +91,11 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
}
|
||||
}
|
||||
|
||||
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
|
||||
|
||||
self.listMonitorDidChange(monitor)
|
||||
}
|
||||
|
||||
// MARK: UITableViewDataSource
|
||||
|
||||
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
@@ -148,7 +153,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
label: "Model V1",
|
||||
entityType: OrganismV1.self,
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
),
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
)
|
||||
),
|
||||
@@ -156,7 +164,13 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
label: "Model V2",
|
||||
entityType: OrganismV2.self,
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: [
|
||||
"MigrationDemo": "MigrationDemoV2",
|
||||
"MigrationDemoV3": "MigrationDemoV2"
|
||||
]
|
||||
),
|
||||
migrationChain: [
|
||||
"MigrationDemo": "MigrationDemoV2",
|
||||
"MigrationDemoV3": "MigrationDemoV2"
|
||||
@@ -167,7 +181,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
label: "Model V3",
|
||||
entityType: OrganismV3.self,
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
XcodeDataModelSchema.from(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
),
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ private struct Static {
|
||||
|
||||
static let facebookStack: DataStack = {
|
||||
|
||||
let dataStack = DataStack(modelName: "StackSetupDemo")
|
||||
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
|
||||
try! dataStack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "AccountsDemo_FB_Male.sqlite",
|
||||
@@ -55,7 +55,7 @@ private struct Static {
|
||||
|
||||
static let twitterStack: DataStack = {
|
||||
|
||||
let dataStack = DataStack(modelName: "StackSetupDemo")
|
||||
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
|
||||
try! dataStack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "AccountsDemo_TW_Male.sqlite",
|
||||
|
||||
@@ -131,7 +131,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
|
||||
// none
|
||||
}
|
||||
|
||||
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPath>) {
|
||||
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<RawKeyPath>) {
|
||||
|
||||
if let mapView = self.mapView {
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ import CoreStore
|
||||
|
||||
class Animal: CoreStoreObject {
|
||||
|
||||
let species = Value.Required<String>("species", default: "Swift")
|
||||
let species = Value.Required<String>("species", initial: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<Color>("color")
|
||||
}
|
||||
@@ -45,21 +45,66 @@ class Animal: CoreStoreObject {
|
||||
class Dog: Animal {
|
||||
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let age = Value.Required<Int>("age", default: 1)
|
||||
let age = Value.Required<Int>("age", initial: 1)
|
||||
let friends = Relationship.ToManyOrdered<Dog>("friends")
|
||||
let friendedBy = Relationship.ToManyUnordered<Dog>("friendedBy", inverse: { $0.friends })
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let title = Value.Required<String>("title", default: "Mr.")
|
||||
|
||||
let title = Value.Required<String>(
|
||||
"title",
|
||||
initial: "Mr.",
|
||||
customSetter: Person.setTitle
|
||||
)
|
||||
|
||||
let name = Value.Required<String>(
|
||||
"name",
|
||||
customGetter: { (`self`, getValue) in
|
||||
|
||||
return "\(self.title.value) \(getValue())"
|
||||
}
|
||||
initial: "",
|
||||
customSetter: Person.setName
|
||||
)
|
||||
|
||||
let displayName = Value.Optional<String>(
|
||||
"displayName",
|
||||
isTransient: true,
|
||||
customGetter: Person.getDisplayName(_:),
|
||||
affectedByKeyPaths: Person.keyPathsAffectingDisplayName()
|
||||
)
|
||||
|
||||
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
|
||||
|
||||
private static func setTitle(_ partialObject: PartialObject<Person>, _ newValue: String) {
|
||||
|
||||
partialObject.setPrimitiveValue(newValue, for: { $0.title })
|
||||
partialObject.setPrimitiveValue(nil, for: { $0.displayName })
|
||||
}
|
||||
|
||||
private static func setName(_ partialObject: PartialObject<Person>, _ newValue: String) {
|
||||
|
||||
partialObject.setPrimitiveValue(newValue, for: { $0.name })
|
||||
partialObject.setPrimitiveValue(nil, for: { $0.displayName })
|
||||
}
|
||||
|
||||
static func getDisplayName(_ partialObject: PartialObject<Person>) -> String? {
|
||||
|
||||
if let displayName = partialObject.primitiveValue(for: { $0.displayName }) {
|
||||
|
||||
return displayName
|
||||
}
|
||||
let title = partialObject.value(for: { $0.title })
|
||||
let name = partialObject.value(for: { $0.name })
|
||||
let displayName = "\(title) \(name)"
|
||||
partialObject.setPrimitiveValue(displayName, for: { $0.displayName })
|
||||
return displayName
|
||||
}
|
||||
|
||||
static func keyPathsAffectingDisplayName() -> Set<String> {
|
||||
|
||||
return [
|
||||
self.keyPath({ $0.title }),
|
||||
self.keyPath({ $0.name })
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,11 +169,25 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
let person = transaction.create(Into<Person>())
|
||||
XCTAssertTrue(person.pets.value.isEmpty)
|
||||
|
||||
XCTAssertEqual(
|
||||
object_getClass(person.rawObject!).keyPathsForValuesAffectingValue(forKey: "displayName"),
|
||||
["title", "name"]
|
||||
)
|
||||
|
||||
person.name .= "Joe"
|
||||
|
||||
XCTAssertEqual(person.rawObject!.value(forKey: "name") as! String?, "Joe")
|
||||
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "Mr. Joe")
|
||||
|
||||
person.rawObject!.setValue("AAAA", forKey: "displayName")
|
||||
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "AAAA")
|
||||
|
||||
person.name .= "John"
|
||||
XCTAssertEqual(person.name.value, "Mr. John") // Custom getter
|
||||
XCTAssertEqual(person.name.value, "John")
|
||||
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
|
||||
|
||||
person.title .= "Sir"
|
||||
XCTAssertEqual(person.name.value, "Sir John")
|
||||
XCTAssertEqual(person.displayName.value, "Sir John")
|
||||
|
||||
person.pets.value.insert(dog)
|
||||
XCTAssertEqual(person.pets.count, 1)
|
||||
|
||||
@@ -36,33 +36,33 @@ class ImportTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatAttributeProtocols_BehaveCorrectly() {
|
||||
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: true))?.boolValue, true)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT))
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: true))?.boolValue, true)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT))
|
||||
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
||||
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
||||
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
||||
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
||||
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
||||
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: true)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int16.max)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int32.max)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int64.max)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: MAXFLOAT)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Double(MAXFLOAT))))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: true)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT)))
|
||||
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT))))
|
||||
|
||||
XCTAssertEqual(true.cs_toQueryableNativeType(), NSNumber(value: true))
|
||||
XCTAssertEqual(Int16.max.cs_toQueryableNativeType(), NSNumber(value: Int16.max))
|
||||
|
||||
@@ -198,60 +198,58 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
return events == 0
|
||||
}
|
||||
)
|
||||
for _ in 1 ... 2 {
|
||||
|
||||
let didUpdateObjectExpectation = self.expectation(
|
||||
forNotification: "listMonitor:didUpdateObject:atIndexPath:",
|
||||
object: observer,
|
||||
handler: { (note) -> Bool in
|
||||
|
||||
let didUpdateObjectExpectation = self.expectation(
|
||||
forNotification: "listMonitor:didUpdateObject:atIndexPath:",
|
||||
object: observer,
|
||||
handler: { (note) -> Bool in
|
||||
|
||||
XCTAssert(events == 1 || events == 2)
|
||||
|
||||
let userInfo = note.userInfo
|
||||
XCTAssertNotNil(userInfo)
|
||||
XCTAssertEqual(
|
||||
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
|
||||
switch object?.testEntityID {
|
||||
|
||||
XCTAssert(events == 1 || events == 2)
|
||||
case NSNumber(value: 101)?:
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
|
||||
let userInfo = note.userInfo
|
||||
XCTAssertNotNil(userInfo)
|
||||
XCTAssertEqual(
|
||||
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
|
||||
["indexPath", "object"]
|
||||
)
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:11")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
case NSNumber(value: 102)?:
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
|
||||
switch object?.testEntityID {
|
||||
|
||||
case NSNumber(value: 101)?:
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:11")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||
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(object?.testBoolean, NSNumber(value: false))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:22")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!)
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
defer {
|
||||
|
||||
events += 1
|
||||
}
|
||||
return events == 1 || events == 2
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:22")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!)
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
}
|
||||
defer {
|
||||
|
||||
events += 1
|
||||
}
|
||||
return events == 1 || events == 2
|
||||
}
|
||||
)
|
||||
let didChangeExpectation = self.expectation(
|
||||
forNotification: "listMonitorDidChange:",
|
||||
object: observer,
|
||||
@@ -453,38 +451,35 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
return events == 0
|
||||
}
|
||||
)
|
||||
for _ in 1 ... 2 {
|
||||
|
||||
let didUpdateObjectExpectation = self.expectation(
|
||||
forNotification: "listMonitor:didDeleteObject:fromIndexPath:",
|
||||
object: observer,
|
||||
handler: { (note) -> Bool in
|
||||
let didUpdateObjectExpectation = self.expectation(
|
||||
forNotification: "listMonitor:didDeleteObject:fromIndexPath:",
|
||||
object: observer,
|
||||
handler: { (note) -> Bool in
|
||||
|
||||
XCTAssert(events == 1 || events == 2)
|
||||
|
||||
let userInfo = note.userInfo
|
||||
XCTAssertNotNil(userInfo)
|
||||
XCTAssertEqual(
|
||||
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.isDeleted, true)
|
||||
|
||||
defer {
|
||||
|
||||
XCTAssert(events == 1 || events == 2)
|
||||
|
||||
let userInfo = note.userInfo
|
||||
XCTAssertNotNil(userInfo)
|
||||
XCTAssertEqual(
|
||||
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
|
||||
["indexPath", "object"]
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.isDeleted, true)
|
||||
|
||||
defer {
|
||||
|
||||
events += 1
|
||||
}
|
||||
return events == 1 || events == 2
|
||||
events += 1
|
||||
}
|
||||
)
|
||||
}
|
||||
return events == 1 || events == 2
|
||||
}
|
||||
)
|
||||
let didDeleteSectionExpectation = self.expectation(
|
||||
forNotification: "listMonitor:didDeleteSection:fromSectionIndex:",
|
||||
object: observer,
|
||||
@@ -531,10 +526,11 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
transaction.deleteAll(
|
||||
let count = transaction.deleteAll(
|
||||
From<TestEntity1>(),
|
||||
Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
|
||||
)
|
||||
XCTAssertEqual(count, 2)
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
@@ -219,7 +219,7 @@ class TestObjectObserver: ObjectObserver {
|
||||
)
|
||||
}
|
||||
|
||||
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, didUpdateObject object: TestEntity1, changedPersistentKeys: Set<KeyPath>) {
|
||||
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, didUpdateObject object: TestEntity1, changedPersistentKeys: Set<String>) {
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),
|
||||
|
||||
@@ -256,6 +256,21 @@ final class WhereTests: XCTestCase {
|
||||
XCTAssertEqual(andWhere.predicate, andPredicate)
|
||||
XCTAssertEqual(andWhere, whereClause1 && whereClause2 && whereClause3)
|
||||
}
|
||||
do {
|
||||
|
||||
let andWhere = whereClause1 && whereClause2 && whereClause3
|
||||
let noneWhere: Where? = nil
|
||||
let someWhere: Where? = Where("key4", isEqualTo: "value4")
|
||||
|
||||
|
||||
let finalNoneWhere = andWhere && noneWhere
|
||||
let finalSomeWhere = andWhere && someWhere
|
||||
let unwrappedFinalSomeWhere = andWhere && someWhere!
|
||||
|
||||
|
||||
XCTAssertEqual(andWhere.predicate, finalNoneWhere.predicate)
|
||||
XCTAssertEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
|
||||
}
|
||||
do {
|
||||
|
||||
let orWhere = whereClause1 || whereClause2 || whereClause3
|
||||
@@ -272,6 +287,21 @@ final class WhereTests: XCTestCase {
|
||||
XCTAssertEqual(orWhere.predicate, orPredicate)
|
||||
XCTAssertEqual(orWhere, whereClause1 || whereClause2 || whereClause3)
|
||||
}
|
||||
do {
|
||||
|
||||
let orWhere = whereClause1 || whereClause2 || whereClause3
|
||||
let noneWhere: Where? = nil
|
||||
let someWhere: Where? = Where("key4", isEqualTo: "value4")
|
||||
|
||||
|
||||
let finalNoneWhere = orWhere && noneWhere
|
||||
let finalSomeWhere = orWhere && someWhere
|
||||
let unwrappedFinalSomeWhere = orWhere && someWhere!
|
||||
|
||||
XCTAssertEqual(orWhere.predicate, finalNoneWhere.predicate)
|
||||
XCTAssertEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@objc
|
||||
|
||||
122
README.md
122
README.md
@@ -18,9 +18,12 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
|
||||
<br />
|
||||
</p>
|
||||
|
||||
* **Swift 3.1:** iOS 8+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+
|
||||
* **Swift 3.2:** iOS 8+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+
|
||||
* Other Swift versions: [Swift 3.1(version 4.1.4)](https://github.com/JohnEstropia/CoreStore/tree/4.1.4), [Swift 4.0](https://github.com/JohnEstropia/CoreStore/tree/5.0.0)
|
||||
|
||||
Upgrading from CoreStore 3.x to 4.x? Check out the [new features](#features) and make sure to read the [Migration guide](#upgrading-from-3xx-to-4xx).
|
||||
Upgrading from CoreStore 4.1 (Swift 3.1) to 4.2 (Swift 3.2)? Check out the [new features](#features) and make sure to read the [Change logs](https://github.com/JohnEstropia/CoreStore/releases).
|
||||
|
||||
CoreStore is now part of the [Swift Source Compatibility projects](https://swift.org/source-compatibility/#current-list-of-projects).
|
||||
|
||||
|
||||
## Why use CoreStore?
|
||||
@@ -35,9 +38,9 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep
|
||||
- **Clean fetching and querying API.** Fetching objects is easy, but querying for raw aggregates (`min`, `max`, etc.) and raw property values is now just as convenient. *(See [Fetching and querying](#fetching-and-querying))*
|
||||
- **Type-safe, easy to configure observers.** You don't have to deal with the burden of setting up `NSFetchedResultsController`s and KVO. As an added bonus, `ListMonitor`s and `ObjectMonitor`s can have multiple observers. This means you can have multiple view controllers efficiently share a single resource! *(See [Observing changes and notifications](#observing-changes-and-notifications))*
|
||||
- **Efficient importing utilities.** Map your entities once with their corresponding import source (JSON for example), and importing from *transactions* becomes elegant. Uniquing is also done with an efficient find-and-replace algorithm. *(See [Importing data](#importing-data))*
|
||||
- ⭐️ **New in 4.0: Say goodbye to *.xcdatamodeld* files!** The new `CoreStoreObject` is *the* replacement to `NSManagedObject`. `CoreStoreObject` subclasses can declare type-safe properties all in Swift code, no need to maintain separate resource files for the models. As bonus, these special properties support custom types, and can be used to create type-safe keypaths and queries. *(See [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects))*
|
||||
- **Say goodbye to *.xcdatamodeld* files!** The new `CoreStoreObject` is *the* replacement to `NSManagedObject`. `CoreStoreObject` subclasses can declare type-safe properties all in Swift code, no need to maintain separate resource files for the models. As bonus, these special properties support custom types, and can be used to create type-safe keypaths and queries. *(See [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects))*
|
||||
- **Progressive migrations.** No need to think how to migrate from all previous model versions to your latest model. Just tell the `DataStack` the sequence of version strings (`MigrationChain`s) and CoreStore will automatically use progressive migrations when needed. *(See [Migrations](#migrations))*
|
||||
- ⭐️ **New in 4.0: Easier custom migrations.** Say goodbye to *.xcmappingmodel* files; CoreStore can now infer entity mappings when possible, while still allowing an easy way to write custom mappings. *(See [Migrations](#migrations))*
|
||||
- **Easier custom migrations.** Say goodbye to *.xcmappingmodel* files; CoreStore can now infer entity mappings when possible, while still allowing an easy way to write custom mappings. *(See [Migrations](#migrations))*
|
||||
- **Plug-in your own logging framework.** Although a default logger is built-in, all logging, asserting, and error reporting can be funneled to `CoreStoreLogger` protocol implementations. *(See [Logging and error reporting](#logging-and-error-reporting))*
|
||||
- **Heavy support for multiple persistent stores per data stack.** CoreStore lets you manage separate stores in a single `DataStack`, just the way *.xcdatamodeld* configurations are designed to. CoreStore will also manage one stack by default, but you can create and manage as many as you need. *(See [Setting up](#setting-up))*
|
||||
- **Free to name entities and their class names independently.** CoreStore gets around a restriction with other Core Data wrappers where the entity name should be the same as the `NSManagedObject` subclass name. CoreStore loads entity-to-class mappings from the managed object model file, so you can assign different names for the entities and their class names.
|
||||
@@ -88,11 +91,10 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep
|
||||
- [Observe a list of objects](#observe-a-list-of-objects)
|
||||
- [Objective-C support](#objective-c-support)
|
||||
- [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects)
|
||||
- [`VersionLock`s](#versionlocks)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Installation](#installation)
|
||||
- [Changesets](#changesets)
|
||||
- [Upgrading from 3.x.x to 4.x.x](#upgrading-from-3xx-to-4xx)
|
||||
- [Other Releases](#other-releases)
|
||||
- [Contact](#contact)
|
||||
- [Who uses CoreStore?](#who-uses-corestore)
|
||||
- [License](#license)
|
||||
@@ -457,6 +459,55 @@ CoreStore.defaultStack = DataStack(
|
||||
)
|
||||
```
|
||||
|
||||
**`CoreStoreSchema`-based model versions with progressive migration**
|
||||
```swift
|
||||
typealias Animal = V2.Animal
|
||||
typealias Dog = V2.Dog
|
||||
typealias Person = V2.Person
|
||||
enum V2 {
|
||||
class Animal: CoreStoreObject {
|
||||
// ...
|
||||
}
|
||||
class Dog: Animal {
|
||||
// ...
|
||||
}
|
||||
class Person: CoreStoreObject {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
enum V1 {
|
||||
class Animal: CoreStoreObject {
|
||||
// ...
|
||||
}
|
||||
class Dog: Animal {
|
||||
// ...
|
||||
}
|
||||
class Person: CoreStoreObject {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
CoreStore.defaultStack = DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<V1.Animal>("Animal", isAbstract: true),
|
||||
Entity<V1.Dog>("Dog"),
|
||||
Entity<V1.Person>("Person")
|
||||
]
|
||||
),
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V2",
|
||||
entities: [
|
||||
Entity<V2.Animal>("Animal", isAbstract: true),
|
||||
Entity<V2.Dog>("Dog"),
|
||||
Entity<V2.Person>("Person")
|
||||
]
|
||||
),
|
||||
migrationChain: ["V1", "V2"]
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
### Starting migrations
|
||||
We have seen `addStorageAndWait(...)` used to initialize our persistent store. As the method name's *~AndWait* suffix suggests though, this method blocks so it should not do long tasks such as store migrations. In fact CoreStore will only attempt a synchronous **lightweight** migration if you explicitly provide the `.allowSynchronousLightweightMigration` option:
|
||||
@@ -1394,7 +1445,7 @@ class MyViewController: UIViewController, ObjectObserver {
|
||||
// ...
|
||||
}
|
||||
|
||||
func objectMonitor(monitor: ObjectMonitor<MyPersonEntity>, didUpdateObject object: MyPersonEntity, changedPersistentKeys: Set<KeyPath>) {
|
||||
func objectMonitor(monitor: ObjectMonitor<MyPersonEntity>, didUpdateObject object: MyPersonEntity, changedPersistentKeys: Set<RawKeyPath>) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@@ -1622,7 +1673,7 @@ To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C sour
|
||||
Starting CoreStore 4.0, we can now create persisted objects without depending on *.xcdatamodeld* Core Data files. The new `CoreStoreObject` subclass replaces `NSManagedObject`, and specially-typed properties declared on these classes will be synthesized as Core Data attributes.
|
||||
```swift
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let species = Value.Required<String>("species", initial: "")
|
||||
}
|
||||
|
||||
class Dog: Animal {
|
||||
@@ -1631,14 +1682,14 @@ class Dog: Animal {
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Required<String>("name")
|
||||
let name = Value.Required<String>("name", initial: "")
|
||||
let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master })
|
||||
}
|
||||
```
|
||||
The property names to be saved to Core Data is specified as the `keyPath` argument. This lets us refactor our Swift code without affecting the underlying database. For example:
|
||||
```swift
|
||||
class Person: CoreStoreObject {
|
||||
private let _name = Value.Required<String>("name")
|
||||
private let _name = Value.Required<String>("name", initial: "")
|
||||
// ...
|
||||
}
|
||||
```
|
||||
@@ -1669,7 +1720,7 @@ These special properties' values can be accessed or mutated using `.value`:
|
||||
```swift
|
||||
CoreStore.perform(
|
||||
asynchronous: { (transaction) in
|
||||
let dog: Dog = CoreStore.fetchOne(From<Dog>())!
|
||||
let dog: Dog = transaction.fetchOne(From<Dog>())!
|
||||
// ...
|
||||
let nickname = dog.nickname.value // String?
|
||||
let species = dog.species.value // String
|
||||
@@ -1696,6 +1747,39 @@ let puppies = CoreStore.fetchAll(
|
||||
|
||||
All CoreStore APIs that are usable with `NSManagedObject`s are also available for `CoreStoreObject`s. These include `ListMonitor`s, `ImportableObject`s, fetching, etc.
|
||||
|
||||
### `VersionLock`s
|
||||
|
||||
While it is convenient to be able to declare entities only in code, it is worrying that we might accidentally change the `CoreStoreObject`'s properties and break our users' model version history. For this, the `CoreStoreSchema` allows us to "lock" our properties to a particular configuration. Any changes to that `VersionLock` will raise an assertion failure during the `CoreStoreSchema` initialization, so you can then look for the commit which changed the `VersionLock` hash.
|
||||
|
||||
To use `VersionLock`s, create the `CoreStoreSchema`, run the app, and look for this particular log message that is automatically printed to the console:
|
||||
|
||||
<img width="700" alt="VersionLock" src="https://cloud.githubusercontent.com/assets/3029684/26525632/757f1bd0-4398-11e7-9795-4132a2df0538.png" />
|
||||
|
||||
Copy this dictionary value and use it as the `versionLock:` argument of the `CoreStoreSchema` initializer:
|
||||
```swift
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<Animal>("Animal", isAbstract: true),
|
||||
Entity<Dog>("Dog"),
|
||||
Entity<Person>("Person"),
|
||||
],
|
||||
versionLock: [
|
||||
"Animal": [0x1b59d511019695cf, 0xdeb97e86c5eff179, 0x1cfd80745646cb3, 0x4ff99416175b5b9a],
|
||||
"Dog": [0xe3f0afeb109b283a, 0x29998d292938eb61, 0x6aab788333cfc2a3, 0x492ff1d295910ea7],
|
||||
"Person": [0x66d8bbfd8b21561f, 0xcecec69ecae3570f, 0xc4b73d71256214ef, 0x89b99bfe3e013e8b]
|
||||
]
|
||||
)
|
||||
```
|
||||
You can also get this hash after the `DataStack` has been fully set up by printing to the console:
|
||||
```swift
|
||||
print(CoreStore.defaultStack.modelSchema.printCoreStoreSchema())
|
||||
```
|
||||
|
||||
Once the version lock is set, any changes in the properties or to the model will trigger an assertion failure similar to this:
|
||||
|
||||
<img width="700" alt="VersionLock failure" src="https://cloud.githubusercontent.com/assets/3029684/26525666/92f46f0c-4399-11e7-9395-4379f6f20876.png" />
|
||||
|
||||
|
||||
# Installation
|
||||
- Requires:
|
||||
@@ -1746,22 +1830,6 @@ Add all *.swift* files to your project.
|
||||
To use the Objective-C syntax sugars, import *CoreStoreBridge.h* in your *.m* source files.
|
||||
|
||||
# Changesets
|
||||
### Upgrading from 3.x.x to 4.x.x
|
||||
**Obsoleted**
|
||||
- `LegacySQLiteStore` is now finally obsoleted in favor of `SQLiteStore`. For sqlite files that were created previously with `LegacySQLiteStore`, make sure to use the `SQLiteStore.legacy(...)` factory method to create an `SQLiteStore` that can load the file from the legacy file path.
|
||||
- `SQLiteStore.init(...)`'s `mappingModelBundles` argument is now obsolete. The new initializer accepts a `migrationMappingProviders` optional argument where explicit mapping sources are declared. For reference on how to do this, read on [Custom migrations](#custom-migrations).
|
||||
|
||||
**Deprecated**
|
||||
- `DataStack.beginAsynchronous(...)`, `DataStack.beginSynchronous(...)`, `AsynchronousDataTransaction.commit(...)`, and `SynchronousDataTransaction.commit(...)` are now deprecated in favor of `DataStack.perform(asynchronous:...)` and `DataStack.perform(synchronous:...)` family of methods. These new `perform(...)` methods are auto-commit, meaning the transaction automatically calls `commit()` internally after the transction closure completes. To roll-back and cancel a transaction, call `try transaction.cancel()`. Read [Saving and processing transactions](#saving-and-processing-transactions) for more details.
|
||||
|
||||
**Other Changes**
|
||||
- `ListMonitor.refetch(...)` now works by recreating its internal `NSFetchedResultsController`. Previously `refetch(...)` would only apply new `FetchClause`s on top of previous fetches. Now all `FetchClauses` are required to be passed to `refetch(...)` each time it is called.
|
||||
- New important concepts on "Dynamic Models", "Schema", and "Schema Histories".
|
||||
- **Dynamic Models** (`DynamicObject` protocol): These are Core Data object types that any `NSManagedObject` or `CoreStoreObject`s conform to. *(See [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects))*
|
||||
- **Version Schema** (`DynamicSchema` protocol): These types contain info for a single model version, as well as entities that belong to it. Currently supports `XcodeDataModelSchema` (*.xcdatamodeld* file), `CoreStoreSchema`, or `UnsafeDataModelSchema`. *(See [Migrations](#migrations))*
|
||||
- **Schema History** (`SchemaHistory` class): This is now the preferred way to express all models to the `DataStack`. This class contains info to all the `DynamicSchema` across multiple model versions. *(See [Migrations](#migrations))*
|
||||
|
||||
### Other Releases
|
||||
|
||||
For the full Changelog, refer to the [Releases](https://github.com/JohnEstropia/CoreStore/releases) page.
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ 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<T: DynamicObject>(_ into: Into<T>) -> T {
|
||||
public override func create<T>(_ into: Into<T>) -> T {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -133,7 +133,7 @@ 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<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
public override func edit<T>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -210,6 +210,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
group.leave()
|
||||
}
|
||||
group.wait()
|
||||
self.context.reset()
|
||||
}
|
||||
|
||||
|
||||
@@ -266,9 +267,9 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
}
|
||||
switch childTransaction.result {
|
||||
|
||||
case nil: return nil
|
||||
case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges)
|
||||
case (_, let error?)?: return SaveResult(error)
|
||||
case .none: return nil
|
||||
case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
|
||||
case .some(_, let error?): return SaveResult(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
Sources/AttributeProtocol.swift
Normal file
47
Sources/AttributeProtocol.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// AttributeProtocol.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - AttributeProtocol
|
||||
|
||||
internal protocol AttributeProtocol: class {
|
||||
|
||||
static var attributeType: NSAttributeType { get }
|
||||
|
||||
var keyPath: RawKeyPath { get }
|
||||
var isOptional: Bool { get }
|
||||
var isIndexed: Bool { get }
|
||||
var isTransient: Bool { get }
|
||||
var versionHashModifier: () -> String? { get }
|
||||
var renamingIdentifier: () -> String? { get }
|
||||
var defaultValue: () -> Any? { get }
|
||||
var affectedByKeyPaths: () -> Set<String> { get }
|
||||
weak var parentObject: CoreStoreObject? { get set }
|
||||
var getter: CoreStoreManagedObject.CustomGetter? { get }
|
||||
var setter: CoreStoreManagedObject.CustomSetter? { get }
|
||||
}
|
||||
@@ -39,7 +39,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
public func deleteAll<T>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -57,7 +57,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `DynamicObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
public func deleteAll<T>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -121,7 +121,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public func fetchOne<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -137,7 +137,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public func fetchOne<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -153,7 +153,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
public func fetchAll<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -169,7 +169,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
public func fetchAll<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -185,7 +185,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
public func fetchCount<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -201,7 +201,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
public func fetchCount<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -217,7 +217,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -233,7 +233,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -249,7 +249,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -265,7 +265,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -287,7 +287,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
public func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -306,7 +306,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
public func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -325,7 +325,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
public func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -344,7 +344,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
public func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
|
||||
@@ -50,7 +50,7 @@ public /*abstract*/ class 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 func create<T: DynamicObject>(_ into: Into<T>) -> T {
|
||||
public func create<T>(_ into: Into<T>) -> T {
|
||||
|
||||
let entityClass = into.entityClass
|
||||
CoreStore.assert(
|
||||
@@ -141,7 +141,7 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
||||
*/
|
||||
public func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
public func edit<T>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -438,6 +438,11 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
self.context.reset()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `AsynchronousDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
|
||||
|
||||
/**
|
||||
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
||||
@@ -139,9 +139,9 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
public typealias SwiftType = AsynchronousDataTransaction
|
||||
|
||||
public override var bridgeToSwift: AsynchronousDataTransaction {
|
||||
public var bridgeToSwift: AsynchronousDataTransaction {
|
||||
|
||||
return super.bridgeToSwift as! AsynchronousDataTransaction
|
||||
return super.swiftTransaction as! AsynchronousDataTransaction
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: AsynchronousDataTransaction) {
|
||||
@@ -149,9 +149,9 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
super.init(swiftValue as BaseDataTransaction)
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
super.init(swiftValue as! AsynchronousDataTransaction)
|
||||
super.init(swiftValue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(object) as NSManagedObject?
|
||||
return self.swiftTransaction.context.fetchExisting(object) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objectID) as NSManagedObject?
|
||||
return self.swiftTransaction.context.fetchExisting(objectID) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +64,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objects) as [NSManagedObject]
|
||||
return self.swiftTransaction.context.fetchExisting(objects) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objectIDs) as [NSManagedObject]
|
||||
return self.swiftTransaction.context.fetchExisting(objectIDs) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,10 +90,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.fetchOne(from, fetchClauses)
|
||||
return self.swiftTransaction.context.fetchOne(from, fetchClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,10 +107,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.fetchAll(from, fetchClauses)
|
||||
return self.swiftTransaction.context.fetchAll(from, fetchClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,10 +124,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context
|
||||
return self.swiftTransaction.context
|
||||
.fetchCount(from, fetchClauses)
|
||||
.flatMap { NSNumber(value: $0) }
|
||||
}
|
||||
@@ -143,10 +143,10 @@ public extension CSBaseDataTransaction {
|
||||
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.fetchObjectID(from, fetchClauses)
|
||||
return self.swiftTransaction.context.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,10 +163,10 @@ public extension CSBaseDataTransaction {
|
||||
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.queryValue(from, selectClause, queryClauses)
|
||||
return self.swiftTransaction.context.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,9 +183,9 @@ public extension CSBaseDataTransaction {
|
||||
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
||||
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
return self.bridgeToSwift.context.queryAttributes(from, selectClause, queryClauses)
|
||||
return self.swiftTransaction.context.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `BaseDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
public class CSBaseDataTransaction: NSObject {
|
||||
|
||||
// MARK: Object management
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public var hasChanges: Bool {
|
||||
|
||||
return self.bridgeToSwift.hasChanges
|
||||
return self.swiftTransaction.hasChanges
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func createInto(_ into: CSInto) -> Any {
|
||||
|
||||
return self.bridgeToSwift.create(into.bridgeToSwift)
|
||||
return self.swiftTransaction.create(into.bridgeToSwift)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +69,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func editObject(_ object: NSManagedObject?) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.edit(object)
|
||||
return self.swiftTransaction.edit(object)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
|
||||
return self.swiftTransaction.edit(into.bridgeToSwift, objectID)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +93,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deleteObject(_ object: NSManagedObject?) {
|
||||
|
||||
self.bridgeToSwift.delete(object)
|
||||
self.swiftTransaction.delete(object)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +104,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deleteObjects(_ objects: [NSManagedObject]) {
|
||||
|
||||
self.bridgeToSwift.delete(objects)
|
||||
self.swiftTransaction.delete(objects)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,7 +113,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func refreshAndMergeAllObjects() {
|
||||
|
||||
self.bridgeToSwift.refreshAndMergeAllObjects()
|
||||
self.swiftTransaction.refreshAndMergeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjects(entity)
|
||||
return self.swiftTransaction.insertedObjects(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +139,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjectIDs()
|
||||
return self.swiftTransaction.insertedObjectIDs()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +151,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjectIDs(entity)
|
||||
return self.swiftTransaction.insertedObjectIDs(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +163,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjects(entity)
|
||||
return self.swiftTransaction.updatedObjects(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +174,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjectIDs()
|
||||
return self.swiftTransaction.updatedObjectIDs()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +186,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjectIDs(entity)
|
||||
return self.swiftTransaction.updatedObjectIDs(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +198,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjects(entity)
|
||||
return self.swiftTransaction.deletedObjects(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,7 +209,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjectIDs()
|
||||
return self.swiftTransaction.deletedObjectIDs()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +221,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjectIDs(entity)
|
||||
return self.swiftTransaction.deletedObjectIDs(entity)
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
public override var hash: Int {
|
||||
|
||||
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
||||
return ObjectIdentifier(self.swiftTransaction).hashValue
|
||||
}
|
||||
|
||||
public override func isEqual(_ object: Any?) -> Bool {
|
||||
@@ -238,28 +238,20 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
return false
|
||||
}
|
||||
return self.bridgeToSwift === object.bridgeToSwift
|
||||
return self.swiftTransaction === object.swiftTransaction
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
// MARK: Internal
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
internal let swiftTransaction: BaseDataTransaction
|
||||
|
||||
internal init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
self.swiftTransaction = swiftValue
|
||||
super.init()
|
||||
}
|
||||
|
||||
public var bridgeToSwift: BaseDataTransaction {
|
||||
|
||||
return self.swiftTransaction
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let swiftTransaction: BaseDataTransaction
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@@ -267,20 +259,20 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
||||
@objc
|
||||
public func insertedObjects() -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.insertedObjects()
|
||||
return self.swiftTransaction.insertedObjects()
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use -[updatedObjectsOfType:] and pass the specific entity class")
|
||||
@objc
|
||||
public func updatedObjects() -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.updatedObjects()
|
||||
return self.swiftTransaction.updatedObjects()
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use -[deletedObjectsOfType:] and pass the specific entity class")
|
||||
@objc
|
||||
public func deletedObjects() -> Set<NSManagedObject> {
|
||||
|
||||
return self.bridgeToSwift.deletedObjects()
|
||||
return self.swiftTransaction.deletedObjects()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
|
||||
The list of key path strings to group results with
|
||||
*/
|
||||
@objc
|
||||
public var keyPaths: [KeyPath] {
|
||||
public var keyPaths: [RawKeyPath] {
|
||||
|
||||
return self.bridgeToSwift.keyPaths
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
|
||||
- parameter keyPath: a key path string to group results with
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPath: KeyPath) {
|
||||
public convenience init(keyPath: RawKeyPath) {
|
||||
|
||||
self.init(GroupBy(keyPath))
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
|
||||
- parameter keyPaths: a list of key path strings to group results with
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPaths: [KeyPath]) {
|
||||
public convenience init(keyPaths: [RawKeyPath]) {
|
||||
|
||||
self.init(GroupBy(keyPaths))
|
||||
}
|
||||
|
||||
@@ -560,7 +560,6 @@ extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
|
||||
|
||||
fileprivate func downcast() -> ListMonitor<NSManagedObject> {
|
||||
|
||||
@inline(__always)
|
||||
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||
|
||||
return unsafeBitCast(x, to: type)
|
||||
|
||||
@@ -42,7 +42,7 @@ import CoreData
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public protocol CSListObserver: class, AnyObject {
|
||||
public protocol CSListObserver: class {
|
||||
|
||||
/**
|
||||
Handles processing just before a change to the observed list occurs
|
||||
|
||||
@@ -152,7 +152,6 @@ extension ObjectMonitor where ObjectMonitor.ObjectType: NSManagedObject {
|
||||
|
||||
fileprivate func downcast() -> ObjectMonitor<NSManagedObject> {
|
||||
|
||||
@inline(__always)
|
||||
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||
|
||||
return unsafeBitCast(x, to: type)
|
||||
|
||||
@@ -40,7 +40,7 @@ import CoreData
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public protocol CSObjectObserver: class, AnyObject {
|
||||
public protocol CSObjectObserver: class {
|
||||
|
||||
/**
|
||||
Handles processing just before a change to the observed `object` occurs
|
||||
|
||||
@@ -45,7 +45,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
||||
*/
|
||||
@objc
|
||||
public static func keyPath(_ sectionKeyPath: KeyPath) -> CSSectionBy {
|
||||
public static func keyPath(_ sectionKeyPath: RawKeyPath) -> CSSectionBy {
|
||||
|
||||
return self.init(SectionBy(sectionKeyPath))
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
||||
*/
|
||||
@objc
|
||||
public static func keyPath(_ sectionKeyPath: KeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
|
||||
public static func keyPath(_ sectionKeyPath: RawKeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
|
||||
|
||||
return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer))
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter keyPath: the attribute name
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPath: KeyPath) {
|
||||
public convenience init(keyPath: RawKeyPath) {
|
||||
|
||||
self.init(.attribute(keyPath))
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute
|
||||
*/
|
||||
@objc
|
||||
public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
||||
public static func average(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm {
|
||||
|
||||
return self.init(.average(keyPath, as: alias))
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `SelectTerm` to a `Select` clause for a count query
|
||||
*/
|
||||
@objc
|
||||
public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
||||
public static func count(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm {
|
||||
|
||||
return self.init(.count(keyPath, as: alias))
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute
|
||||
*/
|
||||
@objc
|
||||
public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
||||
public static func maximum(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm {
|
||||
|
||||
return self.init(.maximum(keyPath, as: alias))
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute
|
||||
*/
|
||||
@objc
|
||||
public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
||||
public static func minimum(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm {
|
||||
|
||||
return self.init(.minimum(keyPath, as: alias))
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute
|
||||
*/
|
||||
@objc
|
||||
public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
||||
public static func sum(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm {
|
||||
|
||||
return self.init(.sum(keyPath, as: alias))
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
|
||||
*/
|
||||
@objc
|
||||
public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm {
|
||||
public static func objectIDAs(_ alias: RawKeyPath? = nil) -> CSSelectTerm {
|
||||
|
||||
return self.init(.objectID(as: alias))
|
||||
}
|
||||
@@ -365,7 +365,7 @@ public final class CSSelect: NSObject {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public init<T: SelectResultType>(_ swiftValue: Select<T>) {
|
||||
public init<T>(_ swiftValue: Select<T>) {
|
||||
|
||||
self.attributeType = .undefinedAttributeType
|
||||
self.selectTerms = swiftValue.selectTerms
|
||||
|
||||
@@ -152,7 +152,7 @@ public final class CSSetupResult: NSObject {
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
|
||||
public required init<T: StorageInterface>(_ swiftValue: SetupResult<T>) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface {
|
||||
public required init<T>(_ swiftValue: SetupResult<T>) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface {
|
||||
|
||||
switch swiftValue {
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `SynchronousDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
public final class CSSynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWaitWithError:` method was already called once.
|
||||
@@ -129,9 +129,9 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
public typealias SwiftType = SynchronousDataTransaction
|
||||
|
||||
public override var bridgeToSwift: SynchronousDataTransaction {
|
||||
public var bridgeToSwift: SynchronousDataTransaction {
|
||||
|
||||
return super.bridgeToSwift as! SynchronousDataTransaction
|
||||
return super.swiftTransaction as! SynchronousDataTransaction
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: SynchronousDataTransaction) {
|
||||
@@ -139,9 +139,9 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
super.init(swiftValue as BaseDataTransaction)
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
super.init(swiftValue as! SynchronousDataTransaction)
|
||||
super.init(swiftValue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `UnsafeDataTransaction`
|
||||
*/
|
||||
@objc
|
||||
public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
public final class CSUnsafeDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
|
||||
/**
|
||||
Saves the transaction changes asynchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
|
||||
|
||||
@@ -189,9 +189,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
public typealias SwiftType = UnsafeDataTransaction
|
||||
|
||||
public override var bridgeToSwift: UnsafeDataTransaction {
|
||||
public var bridgeToSwift: UnsafeDataTransaction {
|
||||
|
||||
return super.bridgeToSwift as! UnsafeDataTransaction
|
||||
return super.swiftTransaction as! UnsafeDataTransaction
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: UnsafeDataTransaction) {
|
||||
@@ -199,9 +199,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
super.init(swiftValue as BaseDataTransaction)
|
||||
}
|
||||
|
||||
public required init(_ swiftValue: BaseDataTransaction) {
|
||||
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||
|
||||
super.init(swiftValue as! UnsafeDataTransaction)
|
||||
super.init(swiftValue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
||||
- parameter value: the arguments for the `==` operator
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPath: KeyPath, isEqualTo value: CoreDataNativeType?) {
|
||||
public convenience init(keyPath: RawKeyPath, isEqualTo value: CoreDataNativeType?) {
|
||||
|
||||
self.init(value == nil || value is NSNull
|
||||
? Where("\(keyPath) == nil")
|
||||
@@ -99,7 +99,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
||||
- parameter list: the array to check membership of
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPath: KeyPath, isMemberOf list: [CoreDataNativeType]) {
|
||||
public convenience init(keyPath: RawKeyPath, isMemberOf list: [CoreDataNativeType]) {
|
||||
|
||||
self.init(Where("\(keyPath) IN %@", list as NSArray))
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import CoreData
|
||||
*/
|
||||
public protocol FetchClause {
|
||||
|
||||
func applyToFetchRequest<T: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<T>)
|
||||
func applyToFetchRequest<T>(_ fetchRequest: NSFetchRequest<T>)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public protocol FetchClause {
|
||||
*/
|
||||
public protocol QueryClause {
|
||||
|
||||
func applyToFetchRequest<T: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<T>)
|
||||
func applyToFetchRequest<T>(_ fetchRequest: NSFetchRequest<T>)
|
||||
}
|
||||
|
||||
|
||||
@@ -56,5 +56,5 @@ public protocol QueryClause {
|
||||
*/
|
||||
public protocol DeleteClause {
|
||||
|
||||
func applyToFetchRequest<T: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<T>)
|
||||
func applyToFetchRequest<T>(_ fetchRequest: NSFetchRequest<T>)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import CoreData
|
||||
Objective-C Foundation types that are natively supported by Core Data managed attributes all conform to `CoreDataNativeType`.
|
||||
*/
|
||||
@objc
|
||||
public protocol CoreDataNativeType: class, NSObjectProtocol, AnyObject {}
|
||||
public protocol CoreDataNativeType: class, NSObjectProtocol {}
|
||||
|
||||
|
||||
// MARK: - NSNumber
|
||||
|
||||
@@ -868,7 +868,8 @@ extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvert
|
||||
("storeOptions", self.storeOptions as Any),
|
||||
("fileURL", self.fileURL),
|
||||
("migrationMappingProviders", self.migrationMappingProviders),
|
||||
("localStorageOptions", self.localStorageOptions)
|
||||
("localStorageOptions", self.localStorageOptions),
|
||||
("fileSize", self.fileSize() as Any)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1214,6 +1215,8 @@ extension NSAttributeType: CoreStoreDebugStringConvertible {
|
||||
case .binaryDataAttributeType: return ".binaryDataAttributeType"
|
||||
case .transformableAttributeType: return ".transformableAttributeType"
|
||||
case .objectIDAttributeType: return ".objectIDAttributeType"
|
||||
case .UUIDAttributeType: return ".UUIDAttributeType"
|
||||
case .URIAttributeType: return ".URIAttributeType"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public extension CoreStore {
|
||||
- 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 static func addStorage<T: StorageInterface>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
public static func addStorage<T>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
|
||||
self.defaultStack.addStorage(storage, completion: completion)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public extension CoreStore {
|
||||
- parameter object: the `DynamicObject` to observe changes from
|
||||
- returns: a `ObjectMonitor` that monitors changes to `object`
|
||||
*/
|
||||
public static func monitorObject<T: DynamicObject>(_ object: T) -> ObjectMonitor<T> {
|
||||
public static func monitorObject<T>(_ object: T) -> ObjectMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorObject(object)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public static func monitorList<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorList(from, fetchClauses)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public static func monitorList<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorList(from, fetchClauses)
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
|
||||
public static func monitorList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
|
||||
public static func monitorList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public static func monitorSectionedList<T>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public static func monitorSectionedList<T>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -125,7 +125,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
|
||||
public static func monitorSectionedList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -138,7 +138,7 @@ public extension CoreStore {
|
||||
- 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 static func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
|
||||
public static func monitorSectionedList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public static func fetchOne<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
return self.defaultStack.fetchOne(from, fetchClauses)
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public static func fetchOne<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
return self.defaultStack.fetchOne(from, fetchClauses)
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
public static func fetchAll<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
return self.defaultStack.fetchAll(from, fetchClauses)
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
public static func fetchAll<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
return self.defaultStack.fetchAll(from, fetchClauses)
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
public static func fetchCount<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
return self.defaultStack.fetchCount(from, fetchClauses)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
public static func fetchCount<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
return self.defaultStack.fetchCount(from, fetchClauses)
|
||||
}
|
||||
@@ -154,7 +154,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
public static func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
return self.defaultStack.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
public static func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
return self.defaultStack.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
public static func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
public static func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
public static func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
return self.defaultStack.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -220,7 +220,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
public static func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
return self.defaultStack.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -235,7 +235,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
public static func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
|
||||
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -250,7 +250,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
public static func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
|
||||
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public extension CoreStore {
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be rethrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
|
||||
Using the `defaultStack`, performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be thrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
|
||||
|
||||
- parameter task: the synchronous non-escaping 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`.
|
||||
- parameter waitForAllObservers: When `true`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks. When `false`, this method does not wait for observers to be notified of the changes before returning. This results in lower risk for deadlocks, but the updated data may not have been propagated to the `DataStack` after returning. Defaults to `true`.
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#define CORESTORE_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
|
||||
|
||||
#pragma mark - KeyPath Utilities
|
||||
#pragma mark - RawKeyPath Utilities
|
||||
|
||||
#define CSKeyPath(type, property) ({ \
|
||||
type *_je_keypath_dummy __attribute__((unused)); \
|
||||
|
||||
@@ -235,15 +235,16 @@ CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RE
|
||||
|
||||
- (void)setAffectedStores:(NSArray<NSPersistentStore *> *_Nullable)affectedStores {
|
||||
|
||||
// Bugfix for NSFetchRequest messing up memory management for `affectedStores`
|
||||
// http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified
|
||||
|
||||
if (NSFoundationVersionNumber < NSFoundationVersionNumber10_0) {
|
||||
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
|
||||
if ([processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 11, 0, 0 }]
|
||||
|| ![processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 10, 0, 0 }]) {
|
||||
|
||||
self.safeAffectedStores = affectedStores;
|
||||
[super setAffectedStores:affectedStores];
|
||||
return;
|
||||
}
|
||||
// Bugfix for NSFetchRequest messing up memory management for `affectedStores`
|
||||
// http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified
|
||||
if (self.releaseArray != NULL) {
|
||||
|
||||
CFRelease(self.releaseArray);
|
||||
|
||||
@@ -31,7 +31,7 @@ import Foundation
|
||||
/**
|
||||
`CoreStoreObjectiveCType`s are Objective-C accessible classes that represent CoreStore's Swift types.
|
||||
*/
|
||||
public protocol CoreStoreObjectiveCType: class, AnyObject {
|
||||
public protocol CoreStoreObjectiveCType: class {
|
||||
|
||||
/**
|
||||
The corresponding Swift type
|
||||
|
||||
@@ -34,7 +34,7 @@ internal extension CoreStoreFetchRequest {
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> {
|
||||
internal func dynamicCast<U>() -> NSFetchRequest<U> {
|
||||
|
||||
return unsafeBitCast(self, to: NSFetchRequest<U>.self)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc
|
||||
internal convenience init<T: DynamicObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal convenience init<T>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: dataStack.mainContext,
|
||||
@@ -47,33 +47,18 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal init<T: DynamicObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal init<T>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
_ = from?.applyToFetchRequest(
|
||||
_ = from.applyToFetchRequest(
|
||||
fetchRequest,
|
||||
context: context,
|
||||
applyAffectedStores: false
|
||||
)
|
||||
applyFetchClauses(fetchRequest)
|
||||
|
||||
if let from = from {
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap({ From<T>($0 as! T.Type) }) else {
|
||||
|
||||
CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From<T>.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
|
||||
}
|
||||
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
|
||||
}
|
||||
|
||||
super.init(
|
||||
@@ -98,7 +83,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchedResultsController<U> {
|
||||
internal func dynamicCast<U>() -> NSFetchedResultsController<U> {
|
||||
|
||||
return unsafeBitCast(self, to: NSFetchedResultsController<U>.self)
|
||||
}
|
||||
|
||||
@@ -47,12 +47,6 @@ public enum LogLevel {
|
||||
*/
|
||||
public protocol CoreStoreLogger {
|
||||
|
||||
/**
|
||||
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false` if not implemented.
|
||||
*/
|
||||
// TODO: test before release (rolled back)
|
||||
// var enableObjectConcurrencyDebugging: Bool { get set }
|
||||
|
||||
/**
|
||||
Handles log messages sent by the `CoreStore` framework.
|
||||
|
||||
@@ -100,13 +94,6 @@ public protocol CoreStoreLogger {
|
||||
|
||||
extension CoreStoreLogger {
|
||||
|
||||
// TODO: test before release (rolled back)
|
||||
// public var enableObjectConcurrencyDebugging: Bool {
|
||||
//
|
||||
// get { return false }
|
||||
// set {}
|
||||
// }
|
||||
|
||||
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
|
||||
|
||||
34
Sources/CoreStoreManagedObject.swift
Normal file
34
Sources/CoreStoreManagedObject.swift
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// CoreStoreManagedObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Rommel Estropia on 2017/06/04.
|
||||
// Copyright © 2017 John Rommel Estropia. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - CoreStoreManagedObject
|
||||
|
||||
@objc internal class CoreStoreManagedObject: NSManagedObject {
|
||||
|
||||
internal typealias CustomGetter = @convention(block) (_ rawObject: Any) -> Any?
|
||||
internal typealias CustomSetter = @convention(block) (_ rawObject: Any, _ newValue: Any?) -> Void
|
||||
internal typealias CustomGetterSetter = (getter: CustomGetter?, setter: CustomSetter?)
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
internal static func cs_subclassName(for entity: DynamicEntity, in modelVersion: ModelVersion) -> String {
|
||||
|
||||
return "_\(NSStringFromClass(CoreStoreManagedObject.self))__\(modelVersion)__\(NSStringFromClass(entity.type))__\(entity.entityName)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private enum Static {
|
||||
|
||||
static let queue = DispatchQueue.concurrent("com.coreStore.coreStoreManagerObjectBarrierQueue")
|
||||
static var cache: [ObjectIdentifier: [RawKeyPath: Set<RawKeyPath>]] = [:]
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
let keyPath: String = Person.keyPath { $0.nickname }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Required<V>) -> String {
|
||||
public static func keyPath<O, V>(_ attribute: (Self) -> ValueContainer<O>.Required<V>) -> String {
|
||||
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
@@ -48,11 +48,44 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
let keyPath: String = Person.keyPath { $0.nickname }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> String {
|
||||
public static func keyPath<O, V>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> String {
|
||||
|
||||
return attribute(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Extracts the keyPath string from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let keyPath: String = Person.keyPath { $0.pets }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O, D>(_ relationship: (Self) -> RelationshipContainer<O>.ToOne<D>) -> String {
|
||||
|
||||
return relationship(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Extracts the keyPath string from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let keyPath: String = Person.keyPath { $0.pets }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O, D>(_ relationship: (Self) -> RelationshipContainer<O>.ToManyOrdered<D>) -> String {
|
||||
|
||||
return relationship(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Extracts the keyPath string from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let keyPath: String = Person.keyPath { $0.pets }
|
||||
```
|
||||
*/
|
||||
public static func keyPath<O, D>(_ relationship: (Self) -> RelationshipContainer<O>.ToManyUnordered<D>) -> String {
|
||||
|
||||
return relationship(self.meta).keyPath
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
@@ -67,10 +100,10 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.ascending { $0.age })
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(ascending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func ascending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
public static func orderBy<O, V>(ascending attribute: (Self) -> ValueContainer<O>.Required<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.ascending(attribute(self.meta).keyPath))
|
||||
}
|
||||
@@ -78,10 +111,47 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.descending { $0.age })
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(ascending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func descending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
public static func orderBy<O, V>(ascending attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.ascending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(descending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func orderBy<O, V>(descending attribute: (Self) -> ValueContainer<O>.Required<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.descending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an `OrderBy` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchAll(From<Person>(), Person.orderBy(descending: { $0.age }))
|
||||
```
|
||||
*/
|
||||
public static func orderBy<O, V>(descending attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.descending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "orderBy(ascending:)")
|
||||
public static func ascending<O, V>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.ascending(attribute(self.meta).keyPath))
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "orderBy(descending:)")
|
||||
public static func descending<O, V>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
|
||||
|
||||
return OrderBy(.descending(attribute(self.meta).keyPath))
|
||||
}
|
||||
@@ -163,6 +233,18 @@ public extension ValueContainer.Required {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Required<V>) -> Where where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,4 +275,146 @@ public extension ValueContainer.Optional {
|
||||
|
||||
return !Where(attribute.keyPath, isEqualTo: value)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age < 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func < (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K < %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K < nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age > 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func > (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K > %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K > nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age <= 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func <= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K <= %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K <= nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let person = CoreStore.fetchOne(From<Person>(), Person.where { $0.age >= 20 })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func >= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
|
||||
|
||||
if let value = value {
|
||||
|
||||
return Where("%K >= %@", attribute.keyPath, value)
|
||||
}
|
||||
else {
|
||||
|
||||
return Where("%K >= nil", attribute.keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Value` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Optional<V>) -> Where where S.Iterator.Element == V {
|
||||
|
||||
return Where(attribute.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipContainer.ToOne
|
||||
|
||||
public extension RelationshipContainer.ToOne {
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { $0.master == me })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func == (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where {
|
||||
|
||||
return Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { $0.master != me })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func != (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where {
|
||||
|
||||
return !Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { $0.master ~= me })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where {
|
||||
|
||||
return Where(relationship.keyPath, isEqualTo: object)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause from a `CoreStoreObject.Relationship` property.
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>(), Dog.where { [john, joe, bob] ~= $0.master })
|
||||
```
|
||||
*/
|
||||
@inline(__always)
|
||||
public static func ~= <S: Sequence>(_ sequence: S, _ relationship: RelationshipContainer<O>.ToOne<D>) -> Where where S.Iterator.Element == D {
|
||||
|
||||
return Where(relationship.keyPath, isMemberOf: sequence)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ import Foundation
|
||||
The `CoreStoreObject` is an abstract class for creating CoreStore-managed objects that are more type-safe and more convenient than `NSManagedObject` subclasses. The model entities for `CoreStoreObject` subclasses are inferred from the Swift declaration themselves; no .xcdatamodeld files are needed. To declare persisted attributes and relationships for the `CoreStoreObject` subclass, declare properties of type `Value.Required<T>`, `Value.Optional<T>` for values, or `Relationship.ToOne<T>`, `Relationship.ToManyOrdered<T>`, `Relationship.ToManyUnordered<T>` for relationships.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let species = Value.Required<String>("species", initial: "")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Required<String>("name")
|
||||
let name = Value.Required<String>("name", initial: "")
|
||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||
}
|
||||
```
|
||||
@@ -68,8 +68,8 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
public required init(rawObject: NSManagedObject) {
|
||||
|
||||
self.isMeta = false
|
||||
self.rawObject = rawObject
|
||||
self.initializeAttributes(Mirror(reflecting: self), { [unowned self] in self })
|
||||
self.rawObject = (rawObject as! CoreStoreManagedObject)
|
||||
self.initializeAttributes(Mirror(reflecting: self), self)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,13 +110,13 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let rawObject: NSManagedObject?
|
||||
internal let rawObject: CoreStoreManagedObject?
|
||||
internal let isMeta: Bool
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func initializeAttributes(_ mirror: Mirror, _ parentObject: @escaping () -> CoreStoreObject) {
|
||||
private func initializeAttributes(_ mirror: Mirror, _ parentObject: CoreStoreObject) {
|
||||
|
||||
_ = mirror.superclassMirror.flatMap({ self.initializeAttributes($0, parentObject) })
|
||||
for child in mirror.children {
|
||||
@@ -135,3 +135,26 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - DynamicObject where Self: CoreStoreObject
|
||||
|
||||
public extension DynamicObject where Self: CoreStoreObject {
|
||||
|
||||
/**
|
||||
Returns the `PartialObject` instance for the object, which acts as a fast, type-safe KVC interface for `CoreStoreObject`.
|
||||
*/
|
||||
public func partialObject() -> PartialObject<Self> {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isMeta,
|
||||
"Attempted to create a \(cs_typeName(PartialObject<Self>.self)) from a meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return PartialObject<Self>(self.rawObject!)
|
||||
}
|
||||
|
||||
internal static var meta: Self {
|
||||
|
||||
return self.init(asMeta: ())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ import Foundation
|
||||
The `CoreStoreSchema` describes models written for `CoreStoreObject` Swift class declarations for a particular model version. `CoreStoreObject` entities for a model version should be added to `CoreStoreSchema` instance.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let species = Value.Required<String>("species", initial: "")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Required<String>("name")
|
||||
let name = Value.Required<String>("name", initial: "")
|
||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||
}
|
||||
|
||||
@@ -66,13 +66,13 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
Initializes a `CoreStoreSchema`. Using this initializer only if the entities don't need to be assigned to particular "Configurations". To use multiple configurations (for example, to separate entities in different `StorageInterface`s), use the `init(modelVersion:entitiesByConfiguration:versionLock:)` initializer.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let species = Value.Required<String>("species", initial: "")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Required<String>("name")
|
||||
let name = Value.Required<String>("name", initial: "")
|
||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||
}
|
||||
|
||||
@@ -112,12 +112,12 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
Initializes a `CoreStoreSchema`. Using this initializer if multiple "Configurations" (for example, to separate entities in different `StorageInterface`s) are needed. 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.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let species = Value.Required<String>("species", initial: "")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Required<String>("name")
|
||||
let name = Value.Required<String>("name", initial: "")
|
||||
}
|
||||
|
||||
CoreStore.defaultStack = DataStack(
|
||||
@@ -200,35 +200,44 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
|
||||
public func rawModel() -> NSManagedObjectModel {
|
||||
|
||||
if let cachedRawModel = self.cachedRawModel {
|
||||
return CoreStoreSchema.barrierQueue.sync(flags: .barrier) {
|
||||
|
||||
return cachedRawModel
|
||||
}
|
||||
let rawModel = NSManagedObjectModel()
|
||||
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
|
||||
for entity in self.allEntities {
|
||||
|
||||
let entityDescription = self.entityDescription(
|
||||
for: entity,
|
||||
initializer: CoreStoreSchema.firstPassCreateEntityDescription
|
||||
if let cachedRawModel = self.cachedRawModel {
|
||||
|
||||
return cachedRawModel
|
||||
}
|
||||
let rawModel = NSManagedObjectModel()
|
||||
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
|
||||
var allCustomGettersSetters: [DynamicEntity: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]] = [:]
|
||||
for entity in self.allEntities {
|
||||
|
||||
let (entityDescription, customGetterSetterByKeyPaths) = self.entityDescription(
|
||||
for: entity,
|
||||
initializer: CoreStoreSchema.firstPassCreateEntityDescription(from:in:)
|
||||
)
|
||||
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
|
||||
allCustomGettersSetters[entity] = customGetterSetterByKeyPaths
|
||||
}
|
||||
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
|
||||
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
|
||||
CoreStoreSchema.fourthPassSynthesizeManagedObjectClasses(
|
||||
for: entityDescriptionsByEntity,
|
||||
allCustomGettersSetters: allCustomGettersSetters
|
||||
)
|
||||
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
|
||||
}
|
||||
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
|
||||
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
|
||||
|
||||
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
|
||||
for (configuration, entities) in self.entitiesByConfiguration {
|
||||
|
||||
rawModel.setEntities(
|
||||
entities
|
||||
.map({ entityDescriptionsByEntity[$0]! })
|
||||
.sorted(by: { $0.name! < $1.name! }),
|
||||
forConfigurationName: configuration
|
||||
)
|
||||
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
|
||||
for (configuration, entities) in self.entitiesByConfiguration {
|
||||
|
||||
rawModel.setEntities(
|
||||
entities
|
||||
.map({ entityDescriptionsByEntity[$0]! })
|
||||
.sorted(by: { $0.name! < $1.name! }),
|
||||
forConfigurationName: configuration
|
||||
)
|
||||
}
|
||||
self.cachedRawModel = rawModel
|
||||
return rawModel
|
||||
}
|
||||
self.cachedRawModel = rawModel
|
||||
return rawModel
|
||||
}
|
||||
|
||||
|
||||
@@ -244,28 +253,33 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
private let allEntities: Set<DynamicEntity>
|
||||
|
||||
private var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
|
||||
private var customGettersSettersByEntity: [DynamicEntity: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]] = [:]
|
||||
private weak var cachedRawModel: NSManagedObjectModel?
|
||||
|
||||
private func entityDescription(for entity: DynamicEntity, initializer: (DynamicEntity) -> NSEntityDescription) -> NSEntityDescription {
|
||||
private func entityDescription(for entity: DynamicEntity, initializer: (DynamicEntity, ModelVersion) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter])) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]) {
|
||||
|
||||
if let cachedEntityDescription = self.entityDescriptionsByEntity[entity] {
|
||||
|
||||
return cachedEntityDescription
|
||||
return (cachedEntityDescription, self.customGettersSettersByEntity[entity] ?? [:])
|
||||
}
|
||||
let entityDescription = withoutActuallyEscaping(initializer, do: { $0(entity) })
|
||||
let modelVersion = self.modelVersion
|
||||
let (entityDescription, customGetterSetterByKeyPaths) = withoutActuallyEscaping(initializer, do: { $0(entity, modelVersion) })
|
||||
self.entityDescriptionsByEntity[entity] = entityDescription
|
||||
return entityDescription
|
||||
self.customGettersSettersByEntity[entity] = customGetterSetterByKeyPaths
|
||||
return (entityDescription, customGetterSetterByKeyPaths)
|
||||
}
|
||||
|
||||
private static func firstPassCreateEntityDescription(from entity: DynamicEntity) -> NSEntityDescription {
|
||||
private static func firstPassCreateEntityDescription(from entity: DynamicEntity, in modelVersion: ModelVersion) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]) {
|
||||
|
||||
let entityDescription = NSEntityDescription()
|
||||
entityDescription.coreStoreEntity = entity
|
||||
entityDescription.name = entity.entityName
|
||||
entityDescription.isAbstract = entity.isAbstract
|
||||
entityDescription.versionHashModifier = entity.versionHashModifier
|
||||
entityDescription.managedObjectClassName = NSStringFromClass(NSManagedObject.self)
|
||||
entityDescription.managedObjectClassName = CoreStoreManagedObject.cs_subclassName(for: entity, in: modelVersion)
|
||||
|
||||
var keyPathsByAffectedKeyPaths: [RawKeyPath: Set<RawKeyPath>] = [:]
|
||||
var customGetterSetterByKeyPaths: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter] = [:]
|
||||
func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] {
|
||||
|
||||
var propertyDescriptions: [NSPropertyDescription] = []
|
||||
@@ -279,11 +293,13 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
description.attributeType = type(of: attribute).attributeType
|
||||
description.isOptional = attribute.isOptional
|
||||
description.isIndexed = attribute.isIndexed
|
||||
description.defaultValue = attribute.defaultValue
|
||||
description.defaultValue = attribute.defaultValue()
|
||||
description.isTransient = attribute.isTransient
|
||||
description.versionHashModifier = attribute.versionHashModifier
|
||||
description.renamingIdentifier = attribute.renamingIdentifier
|
||||
description.versionHashModifier = attribute.versionHashModifier()
|
||||
description.renamingIdentifier = attribute.renamingIdentifier()
|
||||
propertyDescriptions.append(description)
|
||||
keyPathsByAffectedKeyPaths[attribute.keyPath] = attribute.affectedByKeyPaths()
|
||||
customGetterSetterByKeyPaths[attribute.keyPath] = (attribute.getter, attribute.setter)
|
||||
|
||||
case let relationship as RelationshipProtocol:
|
||||
let description = NSRelationshipDescription()
|
||||
@@ -292,9 +308,10 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
description.maxCount = relationship.maxCount
|
||||
description.isOrdered = relationship.isOrdered
|
||||
description.deleteRule = relationship.deleteRule
|
||||
description.versionHashModifier = relationship.versionHashModifier
|
||||
description.renamingIdentifier = relationship.renamingIdentifier
|
||||
description.versionHashModifier = relationship.versionHashModifier()
|
||||
description.renamingIdentifier = relationship.renamingIdentifier()
|
||||
propertyDescriptions.append(description)
|
||||
keyPathsByAffectedKeyPaths[relationship.keyPath] = relationship.affectedByKeyPaths()
|
||||
|
||||
default:
|
||||
continue
|
||||
@@ -302,9 +319,9 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
}
|
||||
return propertyDescriptions
|
||||
}
|
||||
|
||||
entityDescription.properties = createProperties(for: entity.type as! CoreStoreObject.Type)
|
||||
return entityDescription
|
||||
entityDescription.keyPathsByAffectedKeyPaths = keyPathsByAffectedKeyPaths
|
||||
return (entityDescription, customGetterSetterByKeyPaths)
|
||||
}
|
||||
|
||||
private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) {
|
||||
@@ -425,4 +442,112 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private static func fourthPassSynthesizeManagedObjectClasses(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription], allCustomGettersSetters: [DynamicEntity: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]]) {
|
||||
|
||||
func createManagedObjectSubclass(for entityDescription: NSEntityDescription, customGetterSetterByKeyPaths: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]?) {
|
||||
|
||||
let superEntity = entityDescription.superentity
|
||||
let className = entityDescription.managedObjectClassName!
|
||||
guard case nil = NSClassFromString(className) as! CoreStoreManagedObject.Type? else {
|
||||
|
||||
return
|
||||
}
|
||||
if let superEntity = superEntity {
|
||||
|
||||
createManagedObjectSubclass(
|
||||
for: superEntity,
|
||||
customGetterSetterByKeyPaths: superEntity.coreStoreEntity.flatMap({ allCustomGettersSetters[$0] })
|
||||
)
|
||||
}
|
||||
let superClass = cs_lazy { () -> CoreStoreManagedObject.Type in
|
||||
|
||||
if let superClassName = superEntity?.managedObjectClassName,
|
||||
let superClass = NSClassFromString(superClassName) {
|
||||
|
||||
return superClass as! CoreStoreManagedObject.Type
|
||||
}
|
||||
return CoreStoreManagedObject.self
|
||||
}
|
||||
let managedObjectClass: AnyClass = className.withCString {
|
||||
|
||||
return objc_allocateClassPair(superClass, $0, 0)!
|
||||
}
|
||||
defer {
|
||||
|
||||
objc_registerClassPair(managedObjectClass)
|
||||
}
|
||||
|
||||
func capitalize(_ string: String) -> String {
|
||||
|
||||
return string.replacingCharacters(
|
||||
in: Range(uncheckedBounds: (string.startIndex, string.index(after: string.startIndex))),
|
||||
with: String(string[string.startIndex]).uppercased()
|
||||
)
|
||||
}
|
||||
for (attributeName, customGetterSetters) in (customGetterSetterByKeyPaths ?? [:])
|
||||
where customGetterSetters.getter != nil || customGetterSetters.setter != nil {
|
||||
|
||||
if let getter = customGetterSetters.getter {
|
||||
|
||||
let getterName = "\(attributeName)"
|
||||
guard class_addMethod(
|
||||
managedObjectClass,
|
||||
NSSelectorFromString(getterName),
|
||||
imp_implementationWithBlock(getter),
|
||||
"@@:") else {
|
||||
|
||||
CoreStore.abort("Could not dynamically add getter method \"\(getterName)\" to class \(cs_typeName(managedObjectClass))")
|
||||
}
|
||||
}
|
||||
if let setter = customGetterSetters.setter {
|
||||
|
||||
let setterName = "set\(capitalize(attributeName)):"
|
||||
guard class_addMethod(
|
||||
managedObjectClass,
|
||||
NSSelectorFromString(setterName),
|
||||
imp_implementationWithBlock(setter),
|
||||
"v@:@") else {
|
||||
|
||||
CoreStore.abort("Could not dynamically add setter method \"\(setterName)\" to class \(cs_typeName(managedObjectClass))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let newSelector = NSSelectorFromString("cs_keyPathsForValuesAffectingValueForKey:")
|
||||
let keyPathsByAffectedKeyPaths = entityDescription.keyPathsByAffectedKeyPaths
|
||||
let keyPathsForValuesAffectingValue: @convention(block) (Any, String) -> Set<String> = { (instance, keyPath) in
|
||||
|
||||
if let keyPaths = keyPathsByAffectedKeyPaths[keyPath] {
|
||||
|
||||
return keyPaths
|
||||
}
|
||||
return []
|
||||
}
|
||||
let origSelector = #selector(NSManagedObject.keyPathsForValuesAffectingValue(forKey:))
|
||||
|
||||
let metaClass: AnyClass = object_getClass(managedObjectClass)!
|
||||
let origMethod = class_getClassMethod(managedObjectClass, origSelector)
|
||||
|
||||
let origImp = method_getImplementation(origMethod)
|
||||
let newImp = imp_implementationWithBlock(keyPathsForValuesAffectingValue)
|
||||
|
||||
if class_addMethod(metaClass, origSelector, newImp, method_getTypeEncoding(origMethod)) {
|
||||
|
||||
class_replaceMethod(metaClass, newSelector, origImp, method_getTypeEncoding(origMethod))
|
||||
}
|
||||
else {
|
||||
|
||||
let newMethod = class_getClassMethod(managedObjectClass, newSelector)
|
||||
method_exchangeImplementations(origMethod, newMethod)
|
||||
}
|
||||
}
|
||||
for (dynamicEntity, entityDescription) in entityDescriptionsByEntity {
|
||||
|
||||
createManagedObjectSubclass(
|
||||
for: entityDescription,
|
||||
customGetterSetterByKeyPaths: allCustomGettersSetters[dynamicEntity]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import Foundation
|
||||
/**
|
||||
A `SchemaMappingProvider` that accepts custom mappings for some entities. Mappings of entities with no `CustomMapping` provided will be automatically calculated if possible.
|
||||
*/
|
||||
open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
/**
|
||||
The source model version for the mapping.
|
||||
@@ -210,7 +210,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
/**
|
||||
Accesses the property value via its keyPath.
|
||||
*/
|
||||
public subscript(attribute: KeyPath) -> Any? {
|
||||
public subscript(attribute: RawKeyPath) -> Any? {
|
||||
|
||||
return self.rawObject.cs_accessValueForKVCKey(attribute)
|
||||
}
|
||||
@@ -267,7 +267,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
/**
|
||||
Accesses or mutates the property value via its keyPath.
|
||||
*/
|
||||
public subscript(attribute: KeyPath) -> Any? {
|
||||
public subscript(attribute: RawKeyPath) -> Any? {
|
||||
|
||||
get { return self.rawObject.cs_accessValueForKVCKey(attribute) }
|
||||
set { self.rawObject.cs_setValue(newValue, forKVCKey: attribute) }
|
||||
@@ -304,7 +304,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]) {
|
||||
internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [RawKeyPath: NSAttributeDescription]) {
|
||||
|
||||
self.rawObject = rawObject
|
||||
self.sourceAttributesByDestinationKey = sourceAttributesByDestinationKey
|
||||
@@ -314,7 +314,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate let rawObject: NSManagedObject
|
||||
fileprivate let sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]
|
||||
fileprivate let sourceAttributesByDestinationKey: [RawKeyPath: NSAttributeDescription]
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
)
|
||||
func expression(forSource sourceEntity: NSEntityDescription) -> NSExpression {
|
||||
|
||||
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), $\(NSMigrationManagerKey).\(#keyPath(NSMigrationManager.sourceContext)), \(false))")
|
||||
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), FUNCTION($\(NSMigrationManagerKey), \"\(#selector(getter: NSMigrationManager.sourceContext))\"), \(false))")
|
||||
}
|
||||
|
||||
let sourceEntitiesByName = sourceModel.entitiesByName
|
||||
@@ -427,22 +427,25 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
let destinationAttribute = destination.attribute
|
||||
let propertyMapping = NSPropertyMapping()
|
||||
propertyMapping.name = destinationAttribute.name
|
||||
propertyMapping.valueExpression = NSExpression(format: "$\(NSMigrationSourceObjectKey).\(sourceAttribute.name)")
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceAttribute.name)\")")
|
||||
attributeMappings.append(propertyMapping)
|
||||
}
|
||||
return attributeMappings
|
||||
}
|
||||
let entityMappingName = entityMapping.name!
|
||||
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
|
||||
|
||||
let sourceRelationships = sourceEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
var relationshipMappings: [NSPropertyMapping] = []
|
||||
for (_, destination) in destinationRelationships {
|
||||
for (renamingIdentifier, destination) in destinationRelationships {
|
||||
|
||||
let sourceRelationship = sourceRelationships[renamingIdentifier]!.relationship
|
||||
let destinationRelationship = destination.relationship
|
||||
let sourceRelationshipName = sourceRelationship.name
|
||||
|
||||
let propertyMapping = NSPropertyMapping()
|
||||
propertyMapping.name = destinationRelationship.name
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"destinationInstancesForSourceRelationshipNamed:sourceInstances:\", \"\(sourceRelationshipName)\", FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceRelationshipName)\"))")
|
||||
relationshipMappings.append(propertyMapping)
|
||||
}
|
||||
return relationshipMappings
|
||||
@@ -474,7 +477,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
let transformedRenamingIdentifiers = Set(destinationAttributes.keys)
|
||||
.intersection(sourceAttributes.keys)
|
||||
|
||||
var sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription] = [:]
|
||||
var sourceAttributesByDestinationKey: [RawKeyPath: NSAttributeDescription] = [:]
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
|
||||
let sourceAttribute = sourceAttributes[renamingIdentifier]!.attribute
|
||||
@@ -483,17 +486,24 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
}
|
||||
userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] = sourceAttributesByDestinationKey
|
||||
}
|
||||
let entityMappingName = entityMapping.name!
|
||||
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
|
||||
|
||||
let sourceRelationships = sourceEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
|
||||
let transformedRenamingIdentifiers = Set(destinationRelationships.keys)
|
||||
.intersection(sourceRelationships.keys)
|
||||
|
||||
var relationshipMappings: [NSPropertyMapping] = []
|
||||
for (_, destination) in destinationRelationships {
|
||||
|
||||
let destinationRelationship = destination.relationship
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
|
||||
let sourceRelationship = sourceRelationships[renamingIdentifier]!.relationship
|
||||
let destinationRelationship = destinationRelationships[renamingIdentifier]!.relationship
|
||||
let sourceRelationshipName = sourceRelationship.name
|
||||
let destinationRelationshipName = destinationRelationship.name
|
||||
|
||||
let propertyMapping = NSPropertyMapping()
|
||||
propertyMapping.name = destinationRelationship.name
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
|
||||
propertyMapping.name = destinationRelationshipName
|
||||
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"destinationInstancesForSourceRelationshipNamed:sourceInstances:\", \"\(sourceRelationshipName)\", FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceRelationshipName)\"))")
|
||||
relationshipMappings.append(propertyMapping)
|
||||
}
|
||||
return relationshipMappings
|
||||
@@ -525,7 +535,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
let userInfo = mapping.userInfo!
|
||||
let transformer = userInfo[CustomEntityMigrationPolicy.UserInfoKey.transformer]! as! CustomMapping.Transformer
|
||||
let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [KeyPath: NSAttributeDescription]
|
||||
let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [RawKeyPath: NSAttributeDescription]
|
||||
|
||||
var destinationObject: UnsafeDestinationObject?
|
||||
try transformer(
|
||||
@@ -545,11 +555,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
)
|
||||
if let dInstance = destinationObject?.rawObject {
|
||||
|
||||
manager.associate(
|
||||
sourceInstance: sInstance,
|
||||
withDestinationInstance: dInstance,
|
||||
for: mapping
|
||||
)
|
||||
manager.associate(sourceInstance: sInstance, withDestinationInstance: dInstance, for: mapping)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,8 +585,8 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
var insertMappings: Set<CustomMapping> = []
|
||||
var copyMappings: Set<CustomMapping> = []
|
||||
var transformMappings: Set<CustomMapping> = []
|
||||
var allMappedSourceKeys: [KeyPath: KeyPath] = [:]
|
||||
var allMappedDestinationKeys: [KeyPath: KeyPath] = [:]
|
||||
var allMappedSourceKeys: [RawKeyPath: RawKeyPath] = [:]
|
||||
var allMappedDestinationKeys: [RawKeyPath: RawKeyPath] = [:]
|
||||
|
||||
let sourceRenamingIdentifiers = sourceModel.cs_resolvedRenamingIdentities()
|
||||
let sourceEntityNames = sourceModel.entitiesByName
|
||||
@@ -670,77 +676,76 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
allMappedSourceKeys[sourceEntity] = destinationEntity
|
||||
allMappedDestinationKeys[destinationEntity] = sourceEntity
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
|
||||
for renamingIdentifier in transformedRenamingIdentifiers {
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
|
||||
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
|
||||
case (nil, nil):
|
||||
if sourceEntity.versionHash == destinationEntity.versionHash {
|
||||
|
||||
case (nil, nil):
|
||||
if sourceEntity.versionHash == destinationEntity.versionHash {
|
||||
|
||||
copyMappings.insert(
|
||||
.copyEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName
|
||||
)
|
||||
copyMappings.insert(
|
||||
.copyEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
transformMappings.insert(
|
||||
.transformEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName,
|
||||
transformer: CustomMapping.inferredTransformation
|
||||
)
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
transformMappings.insert(
|
||||
.transformEntity(
|
||||
sourceEntity: sourceEntityName,
|
||||
destinationEntity: destinationEntityName,
|
||||
transformer: CustomMapping.inferredTransformation
|
||||
)
|
||||
}
|
||||
allMappedSourceKeys[sourceEntityName] = destinationEntityName
|
||||
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
|
||||
|
||||
case (""?, nil):
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
case (nil, ""?):
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
)
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in removedRenamingIdentifiers {
|
||||
allMappedSourceKeys[sourceEntityName] = destinationEntityName
|
||||
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
|
||||
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
switch allMappedSourceKeys[sourceEntityName] {
|
||||
|
||||
case nil:
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in addedRenamingIdentifiers {
|
||||
case (""?, nil):
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch allMappedDestinationKeys[destinationEntityName] {
|
||||
|
||||
case nil:
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
case (nil, ""?):
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in removedRenamingIdentifiers {
|
||||
|
||||
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let sourceEntityName = sourceEntity.name!
|
||||
switch allMappedSourceKeys[sourceEntityName] {
|
||||
|
||||
case nil:
|
||||
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
|
||||
allMappedSourceKeys[sourceEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
for renamingIdentifier in addedRenamingIdentifiers {
|
||||
|
||||
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
|
||||
let destinationEntityName = destinationEntity.name!
|
||||
switch allMappedDestinationKeys[destinationEntityName] {
|
||||
|
||||
case nil:
|
||||
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
|
||||
allMappedDestinationKeys[destinationEntityName] = ""
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return (deleteMappings, insertMappings, copyMappings, transformMappings)
|
||||
|
||||
@@ -47,7 +47,7 @@ public 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: StorageInterface>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
public func addStorage<T>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
|
||||
|
||||
self.coordinator.performAsynchronously {
|
||||
|
||||
@@ -707,6 +707,7 @@ public extension DataStack {
|
||||
|
||||
do {
|
||||
|
||||
try storage.cs_finalizeStorageAndWait(soureModelHint: sourceModel)
|
||||
try migrationManager.migrateStore(
|
||||
from: fileURL,
|
||||
sourceType: type(of: storage).storeType,
|
||||
@@ -716,6 +717,13 @@ public extension DataStack {
|
||||
destinationType: type(of: storage).storeType,
|
||||
destinationOptions: nil
|
||||
)
|
||||
let temporaryStorage = SQLiteStore(
|
||||
fileURL: temporaryFileURL,
|
||||
configuration: storage.configuration,
|
||||
migrationMappingProviders: storage.migrationMappingProviders,
|
||||
localStorageOptions: storage.localStorageOptions
|
||||
)
|
||||
try temporaryStorage.cs_finalizeStorageAndWait(soureModelHint: destinationModel)
|
||||
}
|
||||
catch {
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public extension DataStack {
|
||||
- parameter object: the `DynamicObject` to observe changes from
|
||||
- returns: a `ObjectMonitor` that monitors changes to `object`
|
||||
*/
|
||||
public func monitorObject<T: DynamicObject>(_ object: T) -> ObjectMonitor<T> {
|
||||
public func monitorObject<T>(_ object: T) -> ObjectMonitor<T> {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -54,7 +54,7 @@ public 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<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public func monitorList<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.monitorList(from, fetchClauses)
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public 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<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public func monitorList<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -95,7 +95,7 @@ public 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<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
|
||||
public func monitorList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public 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<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
|
||||
public func monitorList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -138,7 +138,7 @@ public 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<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public func monitorSectionedList<T>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -151,7 +151,7 @@ public 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<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public func monitorSectionedList<T>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -182,7 +182,7 @@ public 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<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
|
||||
public func monitorSectionedList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public 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<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
|
||||
public func monitorSectionedList<T>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
|
||||
@@ -84,7 +84,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public func fetchOne<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -100,7 +100,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public func fetchOne<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -116,7 +116,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
public func fetchAll<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -132,7 +132,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
public func fetchAll<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -148,7 +148,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
public func fetchCount<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -164,7 +164,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
public func fetchCount<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -180,7 +180,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -196,7 +196,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -212,7 +212,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -228,7 +228,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -250,7 +250,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
public func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -269,7 +269,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
public func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -288,7 +288,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
public func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
@@ -307,7 +307,7 @@ extension DataStack: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
public func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
Thread.isMainThread,
|
||||
|
||||
@@ -61,10 +61,6 @@ public extension DataStack {
|
||||
)
|
||||
transaction.transactionQueue.cs_async {
|
||||
|
||||
defer {
|
||||
|
||||
withExtendedLifetime((self, transaction), {})
|
||||
}
|
||||
let userInfo: T
|
||||
do {
|
||||
|
||||
@@ -82,6 +78,10 @@ public extension DataStack {
|
||||
}
|
||||
transaction.autoCommit { (_, error) in
|
||||
|
||||
defer {
|
||||
|
||||
withExtendedLifetime((self, transaction), {})
|
||||
}
|
||||
if let error = error {
|
||||
|
||||
failure(error)
|
||||
@@ -95,7 +95,7 @@ public extension DataStack {
|
||||
}
|
||||
|
||||
/**
|
||||
Performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be rethrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
|
||||
Performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be thrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
|
||||
|
||||
- parameter task: the synchronous non-escaping 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`.
|
||||
- parameter waitForAllObservers: When `true`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks. When `false`, this method does not wait for observers to be notified of the changes before returning. This results in lower risk for deadlocks, but the updated data may not have been propagated to the `DataStack` after returning. Defaults to `true`.
|
||||
@@ -211,9 +211,9 @@ public extension DataStack {
|
||||
}
|
||||
switch transaction.result {
|
||||
|
||||
case nil: return nil
|
||||
case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges)
|
||||
case (_, let error?)?: return SaveResult(error)
|
||||
case .none: return nil
|
||||
case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
|
||||
case .some(_, let error?): return SaveResult(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,9 +105,6 @@ public final class DataStack: Equatable {
|
||||
*/
|
||||
public required init(schemaHistory: SchemaHistory) {
|
||||
|
||||
// TODO: test before release (rolled back)
|
||||
// _ = DataStack.isGloballyInitialized
|
||||
|
||||
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
|
||||
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
||||
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
|
||||
@@ -585,13 +582,6 @@ public final class DataStack: Equatable {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
// TODO: test before release (rolled back)
|
||||
// private static let isGloballyInitialized: Bool = {
|
||||
//
|
||||
// NSManagedObject.cs_swizzleMethodsForLogging()
|
||||
// return true
|
||||
// }()
|
||||
|
||||
private var persistentStoresByFinalConfiguration = [String: NSPersistentStore]()
|
||||
private var finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set<String>]()
|
||||
|
||||
|
||||
@@ -33,12 +33,6 @@ import Foundation
|
||||
*/
|
||||
public final class DefaultLogger: CoreStoreLogger {
|
||||
|
||||
/**
|
||||
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false`.
|
||||
*/
|
||||
// TODO: test before release (rolled back)
|
||||
// public var enableObjectConcurrencyDebugging: Bool = false
|
||||
|
||||
/**
|
||||
Creates a `DefaultLogger`.
|
||||
*/
|
||||
|
||||
@@ -78,12 +78,7 @@ extension NSManagedObject: DynamicObject {
|
||||
|
||||
public class func cs_fromRaw(object: NSManagedObject) -> Self {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSManagedObject>(_ value: Any) -> T {
|
||||
|
||||
return value as! T
|
||||
}
|
||||
return forceCast(object)
|
||||
return unsafeDowncast(object, to: self)
|
||||
}
|
||||
|
||||
public static func cs_matches(object: NSManagedObject) -> Bool {
|
||||
@@ -124,14 +119,13 @@ extension CoreStoreObject {
|
||||
|
||||
if let coreStoreObject = object.coreStoreObject {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: CoreStoreObject>(_ value: CoreStoreObject) -> T {
|
||||
|
||||
return value as! T
|
||||
}
|
||||
return forceCast(coreStoreObject)
|
||||
return unsafeDowncast(coreStoreObject, to: self)
|
||||
}
|
||||
let coreStoreObject = self.init(rawObject: object)
|
||||
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)
|
||||
object.coreStoreObject = coreStoreObject
|
||||
return coreStoreObject
|
||||
}
|
||||
@@ -155,14 +149,3 @@ extension CoreStoreObject {
|
||||
return self.rawObject!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
internal extension DynamicObject where Self: CoreStoreObject {
|
||||
|
||||
internal static var meta: Self {
|
||||
|
||||
return self.init(asMeta: ())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import Foundation
|
||||
public extension DynamicSchema {
|
||||
|
||||
/**
|
||||
Prints the `DynamicSchema` as their corresponding `CoreStoreObject` Swift declarations. This is useful for converting current `XcodeDataModelSchema`-based models into the new `CoreStoreSchema` framework. Additional adjustments may need to be done to the generated source code for "Transformable" attributes.
|
||||
Prints the `DynamicSchema` as their corresponding `CoreStoreObject` Swift declarations. This is useful for converting current `XcodeDataModelSchema`-based models into the new `CoreStoreSchema` framework. Additional adjustments may need to be done to the generated source code; for example: `Transformable` concrete types need to be provided, as well as `default` values.
|
||||
|
||||
- Important: After transitioning to the new `CoreStoreSchema` framework, it is recommended to add the new schema as a new version that the existing versions' `XcodeDataModelSchema` can migrate to. It is discouraged to load existing SQLite files created with `XcodeDataModelSchema` directly into a `CoreStoreSchema`.
|
||||
- returns: a string that represents the source code for the `DynamicSchema` as their corresponding `CoreStoreObject` Swift declarations.
|
||||
@@ -96,72 +96,62 @@ public extension DynamicSchema {
|
||||
|
||||
case .integer16AttributeType:
|
||||
valueType = Int16.self
|
||||
if let defaultValue = (attribute.defaultValue as! Int16.ImportableNativeType?).flatMap(Int16.cs_fromImportableNativeType),
|
||||
defaultValue != Int16.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Int16.QueryableNativeType?).flatMap(Int16.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: \(defaultValue)"
|
||||
defaultString = ", initial: \(defaultValue)"
|
||||
}
|
||||
case .integer32AttributeType:
|
||||
valueType = Int32.self
|
||||
if let defaultValue = (attribute.defaultValue as! Int32.ImportableNativeType?).flatMap(Int32.cs_fromImportableNativeType),
|
||||
defaultValue != Int32.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Int32.QueryableNativeType?).flatMap(Int32.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: \(defaultValue)"
|
||||
defaultString = ", initial: \(defaultValue)"
|
||||
}
|
||||
case .integer64AttributeType:
|
||||
valueType = Int64.self
|
||||
if let defaultValue = (attribute.defaultValue as! Int64.ImportableNativeType?).flatMap(Int64.cs_fromImportableNativeType),
|
||||
defaultValue != Int64.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Int64.QueryableNativeType?).flatMap(Int64.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: \(defaultValue)"
|
||||
defaultString = ", initial: \(defaultValue)"
|
||||
}
|
||||
case .decimalAttributeType:
|
||||
valueType = NSDecimalNumber.self
|
||||
if let defaultValue = (attribute.defaultValue as! NSDecimalNumber.ImportableNativeType?).flatMap(NSDecimalNumber.cs_fromImportableNativeType),
|
||||
defaultValue != NSDecimalNumber.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! NSDecimalNumber?) {
|
||||
|
||||
defaultString = ", default: NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")"
|
||||
defaultString = ", initial: NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")"
|
||||
}
|
||||
case .doubleAttributeType:
|
||||
valueType = Double.self
|
||||
if let defaultValue = (attribute.defaultValue as! Double.ImportableNativeType?).flatMap(Double.cs_fromImportableNativeType),
|
||||
defaultValue != Double.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Double.QueryableNativeType?).flatMap(Double.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: \(defaultValue)"
|
||||
defaultString = ", initial: \(defaultValue)"
|
||||
}
|
||||
case .floatAttributeType:
|
||||
valueType = Float.self
|
||||
if let defaultValue = (attribute.defaultValue as! Float.ImportableNativeType?).flatMap(Float.cs_fromImportableNativeType),
|
||||
defaultValue != Float.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Float.QueryableNativeType?).flatMap(Float.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: \(defaultValue)"
|
||||
defaultString = ", initial: \(defaultValue)"
|
||||
}
|
||||
case .stringAttributeType:
|
||||
valueType = String.self
|
||||
if let defaultValue = (attribute.defaultValue as! String.ImportableNativeType?).flatMap(String.cs_fromImportableNativeType),
|
||||
defaultValue != String.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! String.QueryableNativeType?).flatMap(String.cs_fromQueryableNativeType) {
|
||||
|
||||
// TODO: escape strings
|
||||
defaultString = ", default: \"\(defaultValue)\""
|
||||
defaultString = ", initial: \"\(defaultValue)\""
|
||||
}
|
||||
case .booleanAttributeType:
|
||||
valueType = Bool.self
|
||||
if let defaultValue = (attribute.defaultValue as! Bool.ImportableNativeType?).flatMap(Bool.cs_fromImportableNativeType),
|
||||
defaultValue != Bool.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Bool.QueryableNativeType?).flatMap(Bool.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: \(defaultValue ? "true" : "false")"
|
||||
defaultString = ", initial: \(defaultValue ? "true" : "false")"
|
||||
}
|
||||
case .dateAttributeType:
|
||||
valueType = Date.self
|
||||
if let defaultValue = (attribute.defaultValue as! Date.ImportableNativeType?).flatMap(Date.cs_fromImportableNativeType),
|
||||
defaultValue != Date.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Date.QueryableNativeType?).flatMap(Date.cs_fromQueryableNativeType) {
|
||||
|
||||
defaultString = ", default: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))"
|
||||
defaultString = ", initial: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))"
|
||||
}
|
||||
case .binaryDataAttributeType:
|
||||
valueType = Data.self
|
||||
if let defaultValue = (attribute.defaultValue as! Data.ImportableNativeType?).flatMap(Data.cs_fromImportableNativeType),
|
||||
defaultValue != Data.cs_emptyValue() {
|
||||
if let defaultValue = (attribute.defaultValue as! Data.QueryableNativeType?).flatMap(Data.cs_fromQueryableNativeType) {
|
||||
|
||||
let count = defaultValue.count
|
||||
let bytes = defaultValue.withUnsafeBytes { (pointer: UnsafePointer<UInt8>) in
|
||||
@@ -169,7 +159,7 @@ public extension DynamicSchema {
|
||||
return (0 ..< (count / MemoryLayout<UInt8>.size))
|
||||
.map({ "\("0x\(String(pointer[$0], radix: 16, uppercase: false))")" })
|
||||
}
|
||||
defaultString = ", default: Data(bytes: [\(bytes.joined(separator: ", "))])"
|
||||
defaultString = ", initial: Data(bytes: [\(bytes.joined(separator: ", "))])"
|
||||
}
|
||||
case .transformableAttributeType:
|
||||
if let attributeValueClassName = attribute.attributeValueClassName {
|
||||
@@ -182,11 +172,11 @@ public extension DynamicSchema {
|
||||
}
|
||||
if let defaultValue = attribute.defaultValue {
|
||||
|
||||
defaultString = ", default: /* \"\(defaultValue)\" */"
|
||||
defaultString = ", initial: /* \"\(defaultValue)\" */"
|
||||
}
|
||||
else if !attribute.isOptional {
|
||||
|
||||
defaultString = ", default: /* required */"
|
||||
defaultString = ", initial: /* required */"
|
||||
}
|
||||
default:
|
||||
fatalError("Unsupported attribute type: \(attribute.attributeType.rawValue)")
|
||||
@@ -194,9 +184,11 @@ public extension DynamicSchema {
|
||||
let indexedString = attribute.isIndexed ? ", isIndexed: true" : ""
|
||||
let transientString = attribute.isTransient ? ", isTransient: true" : ""
|
||||
// TODO: escape strings
|
||||
let versionHashModifierString = attribute.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
let versionHashModifierString = attribute.versionHashModifier
|
||||
.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
// TODO: escape strings
|
||||
let renamingIdentifierString = attribute.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? ""
|
||||
let renamingIdentifierString = attribute.renamingIdentifier
|
||||
.flatMap({ ($0 == attributeName ? "" : ", renamingIdentifier: \"\($0)\"") as String }) ?? ""
|
||||
output.append(" let \(attributeName) = \(containerType)<\(String(describing: valueType))>(\"\(attributeName)\"\(indexedString)\(defaultString)\(transientString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
||||
}
|
||||
}
|
||||
@@ -261,8 +253,10 @@ public extension DynamicSchema {
|
||||
fatalError("Unsupported delete rule \((relationship.deleteRule)) for relationship \"\(relationshipQualifier)\"")
|
||||
}
|
||||
}
|
||||
let versionHashModifierString = relationship.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
let renamingIdentifierString = relationship.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? ""
|
||||
let versionHashModifierString = relationship.versionHashModifier
|
||||
.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||
let renamingIdentifierString = relationship.renamingIdentifier
|
||||
.flatMap({ ($0 == relationshipName ? "" : ", renamingIdentifier: \"\($0)\"") as String }) ?? ""
|
||||
output.append(" let \(relationshipName) = \(containerType)<\(relationship.destinationEntity!.name!)>(\"\(relationshipName)\"\(inverseString)\(deleteRuleString)\(minCountString)\(maxCountString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@ import ObjectiveC
|
||||
The `Entity<O>` contains `NSEntityDescription` metadata for `CoreStoreObject` subclasses. Pass the `Entity` instances to `CoreStoreSchema` initializer.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let species = Value.Required<String>("species", initial: "")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Required<String>("name")
|
||||
let name = Value.Required<String>("name", initial: "")
|
||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T?
|
||||
func fetchOne<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T?
|
||||
|
||||
/**
|
||||
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -82,7 +82,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T?
|
||||
func fetchOne<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T?
|
||||
|
||||
/**
|
||||
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -91,7 +91,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]?
|
||||
func fetchAll<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]?
|
||||
|
||||
/**
|
||||
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -100,7 +100,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]?
|
||||
func fetchAll<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]?
|
||||
|
||||
/**
|
||||
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -109,7 +109,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int?
|
||||
func fetchCount<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int?
|
||||
|
||||
/**
|
||||
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -118,7 +118,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int?
|
||||
func fetchCount<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -127,7 +127,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID?
|
||||
func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -136,7 +136,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID?
|
||||
func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -145,7 +145,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]?
|
||||
func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]?
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
@@ -154,7 +154,7 @@ public protocol FetchableSource: class {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]?
|
||||
func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [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.
|
||||
|
||||
@@ -185,6 +185,10 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
)
|
||||
return
|
||||
}
|
||||
guard #available(iOS 9.0, tvOS 9.0, watchOS 9.0, *) else {
|
||||
|
||||
return
|
||||
}
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeObject: anObject,
|
||||
|
||||
@@ -139,7 +139,7 @@ public struct From<T: DynamicObject> {
|
||||
self.findPersistentStores = findPersistentStores
|
||||
}
|
||||
|
||||
internal func applyToFetchRequest<ResultType: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<ResultType>, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool {
|
||||
internal func applyToFetchRequest<ResultType>(_ fetchRequest: NSFetchRequest<ResultType>, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool {
|
||||
|
||||
fetchRequest.entity = context.parentStack!.entityDescription(for: EntityIdentifier(self.entityClass))!
|
||||
guard applyAffectedStores else {
|
||||
@@ -157,7 +157,7 @@ public struct From<T: DynamicObject> {
|
||||
return false
|
||||
}
|
||||
|
||||
internal func applyAffectedStoresForFetchedRequest<U: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<U>, context: NSManagedObjectContext) -> Bool {
|
||||
internal func applyAffectedStoresForFetchedRequest<U>(_ fetchRequest: NSFetchRequest<U>, context: NSManagedObjectContext) -> Bool {
|
||||
|
||||
let stores = self.findPersistentStores(context)
|
||||
fetchRequest.affectedStores = stores
|
||||
|
||||
@@ -37,7 +37,7 @@ public struct GroupBy: QueryClause, Hashable {
|
||||
/**
|
||||
The list of key path strings to group results with
|
||||
*/
|
||||
public let keyPaths: [KeyPath]
|
||||
public let keyPaths: [RawKeyPath]
|
||||
|
||||
/**
|
||||
Initializes a `GroupBy` clause with an empty list of key path strings
|
||||
@@ -53,7 +53,7 @@ public struct GroupBy: QueryClause, Hashable {
|
||||
- parameter keyPath: a key path string to group results with
|
||||
- parameter keyPaths: a series of key path strings to group results with
|
||||
*/
|
||||
public init(_ keyPath: KeyPath, _ keyPaths: KeyPath...) {
|
||||
public init(_ keyPath: RawKeyPath, _ keyPaths: RawKeyPath...) {
|
||||
|
||||
self.init([keyPath] + keyPaths)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public struct GroupBy: QueryClause, Hashable {
|
||||
|
||||
- parameter keyPaths: a list of key path strings to group results with
|
||||
*/
|
||||
public init(_ keyPaths: [KeyPath]) {
|
||||
public init(_ keyPaths: [RawKeyPath]) {
|
||||
|
||||
self.keyPaths = keyPaths
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public struct GroupBy: QueryClause, Hashable {
|
||||
|
||||
// MARK: QueryClause
|
||||
|
||||
public func applyToFetchRequest<ResultType: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<ResultType>) {
|
||||
public func applyToFetchRequest<ResultType>(_ fetchRequest: NSFetchRequest<ResultType>) {
|
||||
|
||||
if let keyPaths = fetchRequest.propertiesToGroupBy as? [String], keyPaths != self.keyPaths {
|
||||
|
||||
|
||||
@@ -425,8 +425,6 @@ public final class ICloudStore: CloudStorage {
|
||||
*/
|
||||
public func cs_eraseStorageAndWait(soureModel: NSManagedObjectModel) throws {
|
||||
|
||||
// TODO: check if attached to persistent store
|
||||
|
||||
let cacheFileURL = self.cacheFileURL
|
||||
try autoreleasepool {
|
||||
|
||||
|
||||
@@ -57,586 +57,121 @@ import CoreGraphics
|
||||
|
||||
In addition, `RawRepresentable` types whose `RawValue` already implements `ImportableAttributeType` only need to declare conformance to `ImportableAttributeType`.
|
||||
*/
|
||||
public protocol ImportableAttributeType: QueryableAttributeType {
|
||||
|
||||
/**
|
||||
The `CoreDataNativeType` for this type.
|
||||
*/
|
||||
associatedtype ImportableNativeType: QueryableNativeType
|
||||
|
||||
/**
|
||||
Returns the default "empty" value for this type.
|
||||
*/
|
||||
@inline(__always)
|
||||
static func cs_emptyValue() -> Self
|
||||
|
||||
/**
|
||||
Creates an instance of this type from its `ImportableNativeType` value.
|
||||
*/
|
||||
@inline(__always)
|
||||
static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self?
|
||||
|
||||
/**
|
||||
Creates `ImportableNativeType` value from this instance.
|
||||
*/
|
||||
@inline(__always)
|
||||
func cs_toImportableNativeType() -> ImportableNativeType
|
||||
}
|
||||
public protocol ImportableAttributeType: QueryableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Bool
|
||||
|
||||
extension Bool: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
extension Bool: ImportableAttributeType {}
|
||||
|
||||
// MARK: - CGFloat
|
||||
|
||||
extension CGFloat: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> CGFloat {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> CGFloat? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension CGFloat: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Data
|
||||
|
||||
extension Data: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSData
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Data {
|
||||
|
||||
return Data()
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Data: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Date
|
||||
|
||||
extension Date: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSDate
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Date {
|
||||
|
||||
return Date(timeIntervalSinceReferenceDate: 0)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Date: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Double
|
||||
|
||||
extension Double: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Double {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Double: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Float
|
||||
|
||||
extension Float: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Float {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Float: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Int
|
||||
|
||||
extension Int: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Int: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Int8
|
||||
|
||||
extension Int8: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int8 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int8? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Int8: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Int16
|
||||
|
||||
extension Int16: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int16 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Int16: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Int32
|
||||
|
||||
extension Int32: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int32 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Int32: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - Int64
|
||||
|
||||
extension Int64: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> Int64 {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension Int64: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - NSData
|
||||
|
||||
extension NSData: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSData
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension NSData: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - NSDate
|
||||
|
||||
extension NSDate: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSDate
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init(timeIntervalSinceReferenceDate: 0)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension NSDate: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - NSNumber
|
||||
|
||||
extension NSNumber: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSNumber
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension NSNumber: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - NSString
|
||||
|
||||
extension NSString: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init()
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension NSString: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - NSURL
|
||||
|
||||
extension NSURL: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
return self.init(string: "")!
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension NSURL: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - NSUUID
|
||||
|
||||
extension NSUUID: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
public class func cs_emptyValue() -> Self {
|
||||
|
||||
enum Static {
|
||||
|
||||
static var zero = Array<UInt8>(repeating: 0, count: 16)
|
||||
}
|
||||
return self.init(uuidBytes: &Static.zero)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension NSUUID: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - String
|
||||
|
||||
extension String: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_emptyValue() -> String {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension String: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - URL
|
||||
|
||||
extension URL: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
public static func cs_emptyValue() -> URL {
|
||||
|
||||
enum Static {
|
||||
|
||||
static let empty = URL(string: "")!
|
||||
}
|
||||
return Static.empty
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> URL? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension URL: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - UUID
|
||||
|
||||
extension UUID: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = NSString
|
||||
|
||||
public static func cs_emptyValue() -> UUID {
|
||||
|
||||
enum Static {
|
||||
|
||||
static let empty: UUID = cs_lazy {
|
||||
|
||||
var zero = Array<UInt8>(repeating: 0, count: 16)
|
||||
return NSUUID(uuidBytes: &zero) as UUID
|
||||
}
|
||||
}
|
||||
return Static.empty
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> UUID? {
|
||||
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
extension UUID: ImportableAttributeType {}
|
||||
|
||||
|
||||
// MARK: - RawRepresentable
|
||||
|
||||
extension RawRepresentable where RawValue: ImportableAttributeType {
|
||||
|
||||
public typealias ImportableNativeType = RawValue.ImportableNativeType
|
||||
|
||||
public static func cs_emptyValue() -> Self {
|
||||
@inline(__always)
|
||||
public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
return self.init(rawValue: RawValue.cs_emptyValue())!
|
||||
return RawValue.cs_fromQueryableNativeType(value).flatMap({ self.init(rawValue: $0) })
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
public func cs_toQueryableNativeType() -> QueryableNativeType {
|
||||
|
||||
return RawValue.cs_fromImportableNativeType(value).flatMap({ self.init(rawValue: $0) })
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self.rawValue.cs_toImportableNativeType()
|
||||
return self.rawValue.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,11 +55,6 @@ import CoreData
|
||||
*/
|
||||
public protocol ImportableUniqueObject: ImportableObject {
|
||||
|
||||
/**
|
||||
The data type for the import source. This is most commonly an json type, `NSDictionary`, or another external source such as `NSUserDefaults`.
|
||||
*/
|
||||
associatedtype ImportSource
|
||||
|
||||
/**
|
||||
The data type for the entity's unique ID attribute
|
||||
*/
|
||||
@@ -123,6 +118,29 @@ public protocol ImportableUniqueObject: ImportableObject {
|
||||
|
||||
// MARK: - ImportableUniqueObject (Default Implementations)
|
||||
|
||||
public extension ImportableUniqueObject where UniqueIDType.QueryableNativeType: CoreDataNativeType {
|
||||
|
||||
var uniqueIDValue: UniqueIDType {
|
||||
|
||||
get {
|
||||
|
||||
return self.cs_toRaw().getValue(
|
||||
forKvcKey: type(of: self).uniqueIDKeyPath,
|
||||
didGetValue: { UniqueIDType.cs_fromQueryableNativeType($0 as! UniqueIDType.QueryableNativeType)! }
|
||||
)
|
||||
}
|
||||
set {
|
||||
|
||||
self.cs_toRaw()
|
||||
.setValue(
|
||||
newValue,
|
||||
forKvcKey: type(of: self).uniqueIDKeyPath,
|
||||
willSetValue: { ($0.cs_toQueryableNativeType() as CoreDataNativeType) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension ImportableUniqueObject {
|
||||
|
||||
static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
|
||||
@@ -173,29 +191,3 @@ public extension ImportableUniqueObject {
|
||||
try self.update(from: source, in: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ImportableUniqueObject (Default Implementations)
|
||||
|
||||
public extension ImportableUniqueObject where Self: DynamicObject {
|
||||
|
||||
var uniqueIDValue: UniqueIDType {
|
||||
|
||||
get {
|
||||
|
||||
return self.cs_toRaw().getValue(
|
||||
forKvcKey: type(of: self).uniqueIDKeyPath,
|
||||
didGetValue: { UniqueIDType.cs_fromImportableNativeType($0 as! UniqueIDType.ImportableNativeType)! }
|
||||
)
|
||||
}
|
||||
set {
|
||||
|
||||
self.cs_toRaw()
|
||||
.setValue(
|
||||
newValue,
|
||||
forKvcKey: type(of: self).uniqueIDKeyPath,
|
||||
willSetValue: { ($0.cs_toImportableNativeType() as! CoreDataNativeType) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import Foundation
|
||||
/**
|
||||
A `SchemaMappingProvider` that tries to infer model migration between two `DynamicSchema` versions by searching all `xcmappingmodel`s from `Bundle.allBundles` or by relying on lightweight migration if possible. Throws an error if lightweight migration is impossible for the two `DynamicSchema`. This mapping is automatically used as a fallback mapping provider, even if no mapping providers are explicitly declared in the `StorageInterface`.
|
||||
*/
|
||||
final class InferredSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
public final class InferredSchemaMappingProvider: Hashable, SchemaMappingProvider {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.0.0</string>
|
||||
<string>4.2.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -103,7 +103,7 @@ public struct Into<T: DynamicObject>: Hashable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == <U: DynamicObject, V: DynamicObject>(lhs: Into<U>, rhs: Into<V>) -> Bool {
|
||||
public static func == <U, V>(lhs: Into<U>, rhs: Into<V>) -> Bool {
|
||||
|
||||
return lhs.entityClass == rhs.entityClass
|
||||
&& lhs.configuration == rhs.configuration
|
||||
|
||||
@@ -86,6 +86,11 @@ public final class LegacySQLiteStore: LocalStorage {
|
||||
|
||||
public var localStorageOptions: LocalStorageOptions
|
||||
|
||||
public func cs_finalizeStorageAndWait(soureModelHint: NSManagedObjectModel) throws {
|
||||
|
||||
fatalError()
|
||||
}
|
||||
|
||||
public func cs_eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws {
|
||||
|
||||
fatalError()
|
||||
|
||||
@@ -600,7 +600,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func == <T: DynamicObject, U: DynamicObject>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
public static func == <T, U>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -610,7 +610,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
|
||||
public static func ~= <T: DynamicObject, U: DynamicObject>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
public static func ~= <T, U>(lhs: ListMonitor<T>, rhs: ListMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -704,13 +704,13 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
guard let `self` = self,
|
||||
let userInfo = note.userInfo,
|
||||
let object = userInfo[String(describing: NSManagedObject.self)] as? ObjectType else {
|
||||
let rawObject = userInfo[String(describing: NSManagedObject.self)] as? NSManagedObject else {
|
||||
|
||||
return
|
||||
}
|
||||
callback(
|
||||
self,
|
||||
object,
|
||||
ObjectType.cs_fromRaw(object: rawObject),
|
||||
userInfo[String(describing: IndexPath.self)] as? IndexPath,
|
||||
userInfo["\(String(describing: IndexPath.self)).New"] as? IndexPath
|
||||
)
|
||||
@@ -997,7 +997,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
|
||||
|
||||
fileprivate var fetchedResultsController: CoreStoreFetchedResultsController
|
||||
fileprivate let taskGroup = DispatchGroup()
|
||||
fileprivate let sectionIndexTransformer: (_ sectionName: KeyPath?) -> String?
|
||||
fileprivate let sectionIndexTransformer: (_ sectionName: RawKeyPath?) -> String?
|
||||
|
||||
private let isSectioned: Bool
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
/**
|
||||
Initializes the `MigrationChain` with a linear order of versions, which becomes the order of the `DataStack`'s progressive migrations.
|
||||
*/
|
||||
public init<T: Collection>(_ elements: T) where T.Iterator.Element == String, T.SubSequence.Iterator.Element == String, T.Index: Comparable {
|
||||
public init<T: Collection>(_ elements: T) where T.Iterator.Element == String {
|
||||
|
||||
CoreStore.assert(Set(elements).count == Array(elements).count, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to duplicate version strings.")
|
||||
|
||||
|
||||
@@ -31,6 +31,17 @@ import Foundation
|
||||
|
||||
internal extension NSEntityDescription {
|
||||
|
||||
@nonobjc
|
||||
internal var dynamicObjectType: DynamicObject.Type? {
|
||||
|
||||
guard let userInfo = self.userInfo,
|
||||
let typeName = userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] as! String? else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return (NSClassFromString(typeName) as! DynamicObject.Type)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal var coreStoreEntity: DynamicEntity? {
|
||||
|
||||
@@ -54,17 +65,65 @@ internal extension NSEntityDescription {
|
||||
|
||||
if let newValue = newValue {
|
||||
|
||||
var userInfo: [AnyHashable : Any] = [
|
||||
UserInfoKey.CoreStoreManagedObjectTypeName: NSStringFromClass(newValue.type),
|
||||
UserInfoKey.CoreStoreManagedObjectEntityName: newValue.entityName,
|
||||
UserInfoKey.CoreStoreManagedObjectIsAbstract: newValue.isAbstract
|
||||
]
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectVersionHashModifier] = newValue.versionHashModifier
|
||||
self.userInfo = userInfo
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] = NSStringFromClass(newValue.type)
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectEntityName] = newValue.entityName
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectIsAbstract] = newValue.isAbstract
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectVersionHashModifier] = newValue.versionHashModifier
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
self.userInfo = [:]
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectTypeName] = nil
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectEntityName] = nil
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectIsAbstract] = nil
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectVersionHashModifier] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal var keyPathsByAffectedKeyPaths: [RawKeyPath: Set<RawKeyPath>] {
|
||||
|
||||
get {
|
||||
|
||||
if let userInfo = self.userInfo,
|
||||
let value = userInfo[UserInfoKey.CoreStoreManagedObjectKeyPathsByAffectedKeyPaths] {
|
||||
|
||||
return value as! [RawKeyPath: Set<RawKeyPath>]
|
||||
}
|
||||
return [:]
|
||||
}
|
||||
set {
|
||||
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectKeyPathsByAffectedKeyPaths] = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal var customGetterSetterByKeyPaths: [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter] {
|
||||
|
||||
get {
|
||||
|
||||
if let userInfo = self.userInfo,
|
||||
let value = userInfo[UserInfoKey.CoreStoreManagedObjectCustomGetterSetterByKeyPaths] {
|
||||
|
||||
return value as! [RawKeyPath: CoreStoreManagedObject.CustomGetterSetter]
|
||||
}
|
||||
return [:]
|
||||
}
|
||||
set {
|
||||
|
||||
cs_setUserInfo { (userInfo) in
|
||||
|
||||
userInfo[UserInfoKey.CoreStoreManagedObjectCustomGetterSetterByKeyPaths] = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,11 +133,22 @@ internal extension NSEntityDescription {
|
||||
|
||||
// MARK: - UserInfoKey
|
||||
|
||||
fileprivate enum UserInfoKey {
|
||||
private enum UserInfoKey {
|
||||
|
||||
fileprivate static let CoreStoreManagedObjectTypeName = "CoreStoreManagedObjectTypeName"
|
||||
fileprivate static let CoreStoreManagedObjectEntityName = "CoreStoreManagedObjectEntityName"
|
||||
fileprivate static let CoreStoreManagedObjectIsAbstract = "CoreStoreManagedObjectIsAbstract"
|
||||
fileprivate static let CoreStoreManagedObjectVersionHashModifier = "CoreStoreManagedObjectVersionHashModifier"
|
||||
|
||||
fileprivate static let CoreStoreManagedObjectKeyPathsByAffectedKeyPaths = "CoreStoreManagedObjectKeyPathsByAffectedKeyPaths"
|
||||
fileprivate static let CoreStoreManagedObjectCustomGetterSetterByKeyPaths = "CoreStoreManagedObjectCustomGetterSetterByKeyPaths"
|
||||
|
||||
}
|
||||
|
||||
private func cs_setUserInfo(_ closure: (_ userInfo: inout [AnyHashable: Any]) -> Void) {
|
||||
|
||||
var userInfo = self.userInfo ?? [:]
|
||||
closure(&userInfo)
|
||||
self.userInfo = userInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ public extension UnsafeDataTransaction {
|
||||
// MARK: - Private
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
fileprivate func createFRC<T: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<T>? = nil, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<T> {
|
||||
fileprivate func createFRC<T: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<T>, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<T> {
|
||||
|
||||
let controller = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
|
||||
@@ -68,12 +68,12 @@ public extension CSUnsafeDataTransaction {
|
||||
// MARK: - Private
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: CSFrom? = nil, sectionBy: CSSectionBy?, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController<NSManagedObject> {
|
||||
fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: CSFrom, sectionBy: CSSectionBy?, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController<NSManagedObject> {
|
||||
|
||||
let controller = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: CoreStoreFetchRequest().dynamicCast(),
|
||||
from: from?.bridgeToSwift,
|
||||
from: from.bridgeToSwift,
|
||||
sectionBy: sectionBy?.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ public extension NSManagedObject {
|
||||
- returns: the primitive value for the KVC key
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func getValue(forKvcKey kvcKey: KeyPath) -> Any? {
|
||||
public func getValue(forKvcKey kvcKey: RawKeyPath) -> Any? {
|
||||
|
||||
self.willAccessValue(forKey: kvcKey)
|
||||
defer {
|
||||
@@ -102,7 +102,7 @@ public extension NSManagedObject {
|
||||
- returns: the primitive value transformed by the `didGetValue` closure
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func getValue<T>(forKvcKey kvcKey: KeyPath, didGetValue: (Any?) throws -> T) rethrows -> T {
|
||||
public func getValue<T>(forKvcKey kvcKey: RawKeyPath, didGetValue: (Any?) throws -> T) rethrows -> T {
|
||||
|
||||
self.willAccessValue(forKey: kvcKey)
|
||||
defer {
|
||||
@@ -121,7 +121,7 @@ public extension NSManagedObject {
|
||||
- returns: the primitive value transformed by the `didGetValue` closure
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func getValue<T>(forKvcKey kvcKey: KeyPath, willGetValue: () throws -> Void, didGetValue: (Any?) throws -> T) rethrows -> T {
|
||||
public func getValue<T>(forKvcKey kvcKey: RawKeyPath, willGetValue: () throws -> Void, didGetValue: (Any?) throws -> T) rethrows -> T {
|
||||
|
||||
self.willAccessValue(forKey: kvcKey)
|
||||
defer {
|
||||
@@ -139,7 +139,7 @@ public extension NSManagedObject {
|
||||
- parameter KVCKey: the KVC key
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPath) {
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: RawKeyPath) {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
@@ -157,7 +157,7 @@ public extension NSManagedObject {
|
||||
- parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`.
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPath, didSetValue: () -> Void) {
|
||||
public func setValue(_ value: Any?, forKvcKey KVCKey: RawKeyPath, didSetValue: () -> Void) {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
@@ -177,7 +177,7 @@ public extension NSManagedObject {
|
||||
- parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`.
|
||||
*/
|
||||
@nonobjc @inline(__always)
|
||||
public func setValue<T>(_ value: T, forKvcKey KVCKey: KeyPath, willSetValue: (T) throws -> Any?, didSetValue: (Any?) -> Void = { _ in }) rethrows {
|
||||
public func setValue<T>(_ value: T, forKvcKey KVCKey: RawKeyPath, willSetValue: (T) throws -> Any?, didSetValue: (Any?) -> Void = { _ in }) rethrows {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
@@ -212,7 +212,7 @@ public extension NSManagedObject {
|
||||
|
||||
@available(*, deprecated, renamed: "getValue(forKvcKey:)")
|
||||
@nonobjc
|
||||
public func accessValueForKVCKey(_ KVCKey: KeyPath) -> Any? {
|
||||
public func accessValueForKVCKey(_ KVCKey: RawKeyPath) -> Any? {
|
||||
|
||||
self.willAccessValue(forKey: KVCKey)
|
||||
defer {
|
||||
@@ -225,7 +225,7 @@ public extension NSManagedObject {
|
||||
@available(*, deprecated, renamed: "getValue(forKvcKey:didGetValue:)")
|
||||
@discardableResult
|
||||
@nonobjc
|
||||
public func accessValueForKVCKey<T>(_ KVCKey: KeyPath, _ didAccessPrimitiveValue: (Any?) throws -> T) rethrows -> T {
|
||||
public func accessValueForKVCKey<T>(_ KVCKey: RawKeyPath, _ didAccessPrimitiveValue: (Any?) throws -> T) rethrows -> T {
|
||||
|
||||
self.willAccessValue(forKey: KVCKey)
|
||||
defer {
|
||||
@@ -237,7 +237,7 @@ public extension NSManagedObject {
|
||||
|
||||
@available(*, deprecated, renamed: "setValue(_:forKvcKey:)")
|
||||
@nonobjc
|
||||
public func setValue(_ value: Any?, forKVCKey KVCKey: KeyPath) {
|
||||
public func setValue(_ value: Any?, forKVCKey KVCKey: RawKeyPath) {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
@@ -250,7 +250,7 @@ public extension NSManagedObject {
|
||||
@available(*, deprecated, renamed: "setValue(_:forKvcKey:didSetValue:)")
|
||||
@discardableResult
|
||||
@nonobjc
|
||||
public func setValue<T>(_ value: Any?, forKVCKey KVCKey: KeyPath, _ didSetPrimitiveValue: (Any?) throws -> T) rethrows -> T {
|
||||
public func setValue<T>(_ value: Any?, forKVCKey KVCKey: RawKeyPath, _ didSetPrimitiveValue: (Any?) throws -> T) rethrows -> T {
|
||||
|
||||
self.willChangeValue(forKey: KVCKey)
|
||||
defer {
|
||||
|
||||
@@ -66,212 +66,4 @@ internal extension NSManagedObject {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: test before release (rolled back)
|
||||
// @nonobjc
|
||||
// internal static func cs_swizzleMethodsForLogging() {
|
||||
//
|
||||
// struct Static {
|
||||
//
|
||||
// static let isSwizzled = Static.swizzle()
|
||||
//
|
||||
// private static func swizzle() -> Bool {
|
||||
//
|
||||
// NSManagedObject.cs_swizzle(
|
||||
// original: #selector(NSManagedObject.willAccessValue(forKey:)),
|
||||
// proxy: #selector(NSManagedObject.cs_willAccessValue(forKey:))
|
||||
// )
|
||||
// NSManagedObject.cs_swizzle(
|
||||
// original: #selector(NSManagedObject.willChangeValue(forKey:)),
|
||||
// proxy: #selector(NSManagedObject.cs_willChangeValue(forKey:))
|
||||
// )
|
||||
// NSManagedObject.cs_swizzle(
|
||||
// original: #selector(NSManagedObject.willChangeValue(forKey:withSetMutation:using:)),
|
||||
// proxy: #selector(NSManagedObject.cs_willChangeValue(forKey:withSetMutation:using:))
|
||||
// )
|
||||
// return true
|
||||
// }
|
||||
// }
|
||||
// assert(Static.isSwizzled)
|
||||
// }
|
||||
//
|
||||
// @nonobjc
|
||||
// private static func cs_swizzle(original originalSelector: Selector, proxy swizzledSelector: Selector) {
|
||||
//
|
||||
// let originalMethod = class_getInstanceMethod(NSManagedObject.self, originalSelector)
|
||||
// let swizzledMethod = class_getInstanceMethod(NSManagedObject.self, swizzledSelector)
|
||||
// let didAddMethod = class_addMethod(
|
||||
// NSManagedObject.self,
|
||||
// originalSelector,
|
||||
// method_getImplementation(swizzledMethod),
|
||||
// method_getTypeEncoding(swizzledMethod)
|
||||
// )
|
||||
// if didAddMethod {
|
||||
//
|
||||
// class_replaceMethod(
|
||||
// NSManagedObject.self,
|
||||
// swizzledSelector,
|
||||
// method_getImplementation(originalMethod),
|
||||
// method_getTypeEncoding(originalMethod)
|
||||
// )
|
||||
// }
|
||||
// else {
|
||||
//
|
||||
// method_exchangeImplementations(originalMethod, swizzledMethod)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private dynamic func cs_willAccessValue(forKey key: String?) {
|
||||
//
|
||||
// self.cs_willAccessValue(forKey: key)
|
||||
//
|
||||
// guard CoreStore.logger.enableObjectConcurrencyDebugging else {
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// guard let context = self.managedObjectContext else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(NSManagedObjectContext.self))."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if context.isTransactionContext {
|
||||
//
|
||||
// guard let transaction = context.parentTransaction else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) after has been deleted from its transaction."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// CoreStore.assert(
|
||||
// transaction.isRunningInAllowedQueue(),
|
||||
// "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) outside its transaction's designated queue."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if context.isDataStackContext {
|
||||
//
|
||||
// guard context.parentStack != nil else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(DataStack.self)).")
|
||||
// return
|
||||
// }
|
||||
// CoreStore.assert(
|
||||
// Thread.isMainThread,
|
||||
// "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) outside the main thread."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private dynamic func cs_willChangeValue(forKey key: String?) {
|
||||
//
|
||||
// self.cs_willChangeValue(forKey: key)
|
||||
//
|
||||
// guard CoreStore.logger.enableObjectConcurrencyDebugging else {
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// guard let context = self.managedObjectContext else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(NSManagedObjectContext.self))."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if context.isTransactionContext {
|
||||
//
|
||||
// guard let transaction = context.parentTransaction else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) after has been deleted from its transaction."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// CoreStore.assert(
|
||||
// transaction.isRunningInAllowedQueue(),
|
||||
// "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) outside its transaction's designated queue."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if context.isDataStackContext {
|
||||
//
|
||||
// guard context.parentStack != nil else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(DataStack.self)).")
|
||||
// return
|
||||
// }
|
||||
// CoreStore.assert(
|
||||
// Thread.isMainThread,
|
||||
// "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) outside the main thread."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private dynamic func cs_willChangeValue(forKey inKey: String, withSetMutation inMutationKind: NSKeyValueSetMutationKind, using inObjects: Set<AnyHashable>) {
|
||||
//
|
||||
// self.cs_willChangeValue(
|
||||
// forKey: inKey,
|
||||
// withSetMutation: inMutationKind,
|
||||
// using: inObjects
|
||||
// )
|
||||
//
|
||||
// guard CoreStore.logger.enableObjectConcurrencyDebugging else {
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// guard let context = self.managedObjectContext else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(NSManagedObjectContext.self))."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if context.isTransactionContext {
|
||||
//
|
||||
// guard let transaction = context.parentTransaction else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) after has been deleted from its transaction."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// CoreStore.assert(
|
||||
// transaction.isRunningInAllowedQueue(),
|
||||
// "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) outside its transaction's designated queue."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if context.isDataStackContext {
|
||||
//
|
||||
// guard context.parentStack != nil else {
|
||||
//
|
||||
// CoreStore.log(
|
||||
// .warning,
|
||||
// message: "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(DataStack.self)).")
|
||||
// return
|
||||
// }
|
||||
// CoreStore.assert(
|
||||
// Thread.isMainThread,
|
||||
// "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) outside the main thread."
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public extension NSManagedObject {
|
||||
- returns: the primitive value for the KVC key
|
||||
*/
|
||||
@objc
|
||||
public func cs_accessValueForKVCKey(_ KVCKey: KeyPath) -> Any? {
|
||||
public func cs_accessValueForKVCKey(_ KVCKey: RawKeyPath) -> Any? {
|
||||
|
||||
return self.getValue(forKvcKey: KVCKey)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public extension NSManagedObject {
|
||||
- parameter KVCKey: the KVC key
|
||||
*/
|
||||
@objc
|
||||
public func cs_setValue(_ value: Any?, forKVCKey KVCKey: KeyPath) {
|
||||
public func cs_setValue(_ value: Any?, forKVCKey KVCKey: RawKeyPath) {
|
||||
|
||||
self.setValue(value, forKvcKey: KVCKey)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
|
||||
return object
|
||||
}
|
||||
return T.cs_fromRaw(object: existingRawObject)
|
||||
return type(of: object).cs_fromRaw(object: existingRawObject)
|
||||
}
|
||||
catch {
|
||||
|
||||
@@ -101,13 +101,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public func fetchOne<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
return self.fetchOne(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public func fetchOne<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -124,13 +124,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
public func fetchAll<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
return self.fetchAll(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
public func fetchAll<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -148,13 +148,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
public func fetchCount<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
return self.fetchCount(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
public func fetchCount<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -168,13 +168,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
return self.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -191,13 +191,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
return self.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -244,13 +244,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
// MARK: QueryableSource
|
||||
|
||||
@nonobjc
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
public func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
return self.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
public func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -269,13 +269,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
public func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
|
||||
return self.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
public func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
@@ -305,13 +305,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource {
|
||||
// MARK: Deleting
|
||||
|
||||
@nonobjc
|
||||
internal func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
internal func deleteAll<T>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
|
||||
return self.deleteAll(from, deleteClauses)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
internal func deleteAll<T>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
|
||||
let fetchRequest = CoreStoreFetchRequest()
|
||||
let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class ObjectMonitor<D: DynamicObject>: Equatable {
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
public static func == <T: DynamicObject, U: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
public static func == <T, U>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public final class ObjectMonitor<D: DynamicObject>: Equatable {
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
public static func ~= <T: DynamicObject, U: DynamicObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
public static func ~= <T, U>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<U>) -> Bool {
|
||||
|
||||
return lhs.fetchedResultsController === rhs.fetchedResultsController
|
||||
}
|
||||
@@ -272,7 +272,7 @@ public final class ObjectMonitor<D: DynamicObject>: Equatable {
|
||||
let fetchedResultsController = CoreStoreFetchedResultsController(
|
||||
context: context,
|
||||
fetchRequest: fetchRequest.dynamicCast(),
|
||||
from: nil as From<ObjectType>?,
|
||||
from: From<ObjectType>([objectID.persistentStore?.configurationName]),
|
||||
applyFetchClauses: Where("SELF", isEqualTo: objectID).applyToFetchRequest
|
||||
)
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public protocol ObjectObserver: class {
|
||||
- parameter object: the `DynamicObject` instance being observed
|
||||
- parameter changedPersistentKeys: a `Set` of key paths for the attributes that were changed. Note that `changedPersistentKeys` only contains keys for attributes/relationships present in the persistent store, thus transient properties will not be reported.
|
||||
*/
|
||||
func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set<KeyPath>)
|
||||
func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set<RawKeyPath>)
|
||||
|
||||
/**
|
||||
Handles processing right after `object` is deleted. (Optional)
|
||||
@@ -81,7 +81,7 @@ public extension ObjectObserver {
|
||||
|
||||
public func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, willUpdateObject object: ObjectEntityType) { }
|
||||
|
||||
public func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set<KeyPath>) { }
|
||||
public func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set<RawKeyPath>) { }
|
||||
|
||||
public func objectMonitor(_ monitor: ObjectMonitor<ObjectEntityType>, didDeleteObject object: ObjectEntityType) { }
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - KeyPath
|
||||
// MARK: - RawKeyPath
|
||||
|
||||
public typealias KeyPath = String
|
||||
public typealias RawKeyPath = String
|
||||
|
||||
|
||||
// MARK: - SortKey
|
||||
@@ -40,14 +40,24 @@ public typealias KeyPath = String
|
||||
public enum SortKey {
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPath` should be sorted in ascending order
|
||||
Indicates that the `RawKeyPath` should be sorted in ascending order
|
||||
*/
|
||||
case ascending(KeyPath)
|
||||
case ascending(RawKeyPath)
|
||||
|
||||
/**
|
||||
Indicates that the `KeyPath` should be sorted in descending order
|
||||
Indicates that the `RawKeyPath` should be sorted in descending order
|
||||
*/
|
||||
case descending(KeyPath)
|
||||
case descending(RawKeyPath)
|
||||
|
||||
/**
|
||||
Indicates that the `RawKeyPath` should be sorted in ascending order in a case-insenstive manner
|
||||
*/
|
||||
case ascendingInsensitive(RawKeyPath)
|
||||
|
||||
/**
|
||||
Indicates that the `RawKeyPath` should be sorted in descending order in a case-insenstive manner
|
||||
*/
|
||||
case descendingInsensitive(RawKeyPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +134,12 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
|
||||
|
||||
case .descending(let keyPath):
|
||||
return NSSortDescriptor(key: keyPath, ascending: false)
|
||||
|
||||
case .ascendingInsensitive(let keyPath):
|
||||
return NSSortDescriptor(key: keyPath, ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
|
||||
|
||||
case .descendingInsensitive(let keyPath):
|
||||
return NSSortDescriptor(key: keyPath, ascending: false, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -143,7 +159,7 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
|
||||
|
||||
// MARK: FetchClause, QueryClause, DeleteClause
|
||||
|
||||
public func applyToFetchRequest<ResultType: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<ResultType>) {
|
||||
public func applyToFetchRequest<ResultType>(_ fetchRequest: NSFetchRequest<ResultType>) {
|
||||
|
||||
if let sortDescriptors = fetchRequest.sortDescriptors, sortDescriptors != self.sortDescriptors {
|
||||
|
||||
@@ -172,3 +188,17 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
|
||||
return (self.sortDescriptors as NSArray).hashValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Sequence where Element == OrderBy
|
||||
|
||||
public extension Sequence where Iterator.Element == OrderBy {
|
||||
|
||||
/**
|
||||
Combines multiple `OrderBy` predicates together
|
||||
*/
|
||||
public func combined() -> OrderBy {
|
||||
|
||||
return OrderBy(self.flatMap({ $0.sortDescriptors }))
|
||||
}
|
||||
}
|
||||
|
||||
240
Sources/PartialObject.swift
Normal file
240
Sources/PartialObject.swift
Normal file
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// PartialObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - PartialObject
|
||||
|
||||
/**
|
||||
A `PartialObject` is only used when overriding getters and setters for `CoreStoreObject` properties. Custom getters and setters are implemented as a closure that "overrides" the default property getter/setter. The closure receives a `PartialObject<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 heavy performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject<O>`, make sure to use `PartialObject<O>.persistentValue(for:)` instead of `PartialObject<O>.value(for:)`, which would unintentionally execute the same closure again recursively.
|
||||
*/
|
||||
public struct PartialObject<O: CoreStoreObject> {
|
||||
|
||||
/**
|
||||
Returns a the actual `CoreStoreObject` instance for the receiver.
|
||||
*/
|
||||
public func completeObject() -> O {
|
||||
|
||||
return O.cs_fromRaw(object: self.rawObject)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Value.Required accessors/mutators
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public func value<V>(for property: (O) -> ValueContainer<O>.Required<V>) -> V {
|
||||
|
||||
return V.cs_fromQueryableNativeType(
|
||||
self.rawObject.value(forKey: property(O.meta).keyPath)! as! V.QueryableNativeType
|
||||
)!
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the property of the receiver specified by a given key to a given value.
|
||||
*/
|
||||
public func setValue<V>(_ value: V, for property: (O) -> ValueContainer<O>.Required<V>) {
|
||||
|
||||
self.rawObject.setValue(
|
||||
value.cs_toQueryableNativeType(),
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the specified property from the managed object’s private internal storage.
|
||||
|
||||
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||
*/
|
||||
public func primitiveValue<V>(for property: (O) -> ValueContainer<O>.Required<V>) -> V {
|
||||
|
||||
return V.cs_fromQueryableNativeType(
|
||||
self.rawObject.primitiveValue(forKey: property(O.meta).keyPath)! as! V.QueryableNativeType
|
||||
)!
|
||||
}
|
||||
|
||||
/**
|
||||
Sets in the object's private internal storage the value of a given property.
|
||||
|
||||
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||
*/
|
||||
public func setPrimitiveValue<V>(_ value: V, for property: (O) -> ValueContainer<O>.Required<V>) {
|
||||
|
||||
self.rawObject.setPrimitiveValue(
|
||||
value.cs_toQueryableNativeType(),
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Value.Optional utilities
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public func value<V>(for property: (O) -> ValueContainer<O>.Optional<V>) -> V? {
|
||||
|
||||
return (self.rawObject.value(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?)
|
||||
.flatMap(V.cs_fromQueryableNativeType)
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the property of the receiver specified by a given key to a given value.
|
||||
*/
|
||||
public func setValue<V>(_ value: V?, for property: (O) -> ValueContainer<O>.Optional<V>) {
|
||||
|
||||
self.rawObject.setValue(
|
||||
value?.cs_toQueryableNativeType(),
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the specified property from the managed object’s private internal storage.
|
||||
|
||||
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||
*/
|
||||
public func primitiveValue<V>(for property: (O) -> ValueContainer<O>.Optional<V>) -> V? {
|
||||
|
||||
return (self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?)
|
||||
.flatMap(V.cs_fromQueryableNativeType)
|
||||
}
|
||||
|
||||
/**
|
||||
Sets in the object's private internal storage the value of a given property.
|
||||
|
||||
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||
*/
|
||||
public func setPrimitiveValue<V>(_ value: V?, for property: (O) -> ValueContainer<O>.Optional<V>) {
|
||||
|
||||
self.rawObject.setPrimitiveValue(
|
||||
value?.cs_toQueryableNativeType(),
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Transformable.Required utilities
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public func value<V>(for property: (O) -> TransformableContainer<O>.Required<V>) -> V {
|
||||
|
||||
return self.rawObject.value(forKey: property(O.meta).keyPath)! as! V
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the property of the receiver specified by a given key to a given value.
|
||||
*/
|
||||
public func setValue<V>(_ value: V, for property: (O) -> TransformableContainer<O>.Required<V>) {
|
||||
|
||||
self.rawObject.setValue(
|
||||
value,
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the specified property from the managed object’s private internal storage.
|
||||
|
||||
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||
*/
|
||||
public func primitiveValue<V>(for property: (O) -> TransformableContainer<O>.Required<V>) -> V {
|
||||
|
||||
return self.rawObject.primitiveValue(forKey: property(O.meta).keyPath)! as! V
|
||||
}
|
||||
|
||||
/**
|
||||
Sets in the object's private internal storage the value of a given property.
|
||||
|
||||
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||
*/
|
||||
public func setPrimitiveValue<V>(_ value: V, for property: (O) -> TransformableContainer<O>.Required<V>) {
|
||||
|
||||
self.rawObject.setPrimitiveValue(
|
||||
value,
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Transformable.Optional utilities
|
||||
|
||||
/**
|
||||
Returns the value for the property identified by a given key.
|
||||
*/
|
||||
public func value<V>(for property: (O) -> TransformableContainer<O>.Optional<V>) -> V? {
|
||||
|
||||
return self.rawObject.value(forKey: property(O.meta).keyPath) as! V?
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the property of the receiver specified by a given key to a given value.
|
||||
*/
|
||||
public func setValue<V>(_ value: V?, for property: (O) -> TransformableContainer<O>.Optional<V>) {
|
||||
|
||||
self.rawObject.setValue(
|
||||
value,
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value for the specified property from the managed object’s private internal storage.
|
||||
|
||||
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||
*/
|
||||
public func primitiveValue<V>(for property: (O) -> TransformableContainer<O>.Optional<V>) -> V? {
|
||||
|
||||
return self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V?
|
||||
}
|
||||
|
||||
/**
|
||||
Sets in the object's private internal storage the value of a given property.
|
||||
|
||||
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||
*/
|
||||
public func setPrimitiveValue<V>(_ value: V?, for property: (O) -> TransformableContainer<O>.Optional<V>) {
|
||||
|
||||
self.rawObject.setPrimitiveValue(
|
||||
value,
|
||||
forKey: property(O.meta).keyPath
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let rawObject: NSManagedObject
|
||||
|
||||
internal init(_ rawObject: NSManagedObject) {
|
||||
|
||||
self.rawObject = rawObject
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public protocol QueryableAttributeType: Hashable, SelectResultType {
|
||||
/**
|
||||
The `CoreDataNativeType` for this type when used in `Select` clauses.
|
||||
*/
|
||||
associatedtype QueryableNativeType: CoreDataNativeType
|
||||
associatedtype QueryableNativeType
|
||||
|
||||
/**
|
||||
The `NSAttributeType` for this type when used in `Select` clauses.
|
||||
@@ -111,7 +111,7 @@ extension Bool: QueryableAttributeType {
|
||||
@inline(__always)
|
||||
public func cs_toQueryableNativeType() -> QueryableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self as QueryableNativeType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ extension CGFloat: QueryableAttributeType {
|
||||
@inline(__always)
|
||||
public func cs_toQueryableNativeType() -> QueryableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self as QueryableNativeType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ extension Data: QueryableAttributeType {
|
||||
@inline(__always)
|
||||
public func cs_toQueryableNativeType() -> QueryableNativeType {
|
||||
|
||||
return self as NSData
|
||||
return self as QueryableNativeType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,12 +342,14 @@ extension NSData: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSData
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .binaryDataAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .binaryDataAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSData>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -369,12 +371,14 @@ extension NSDate: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSDate
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .dateAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .dateAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSDate>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -407,12 +411,14 @@ extension NSManagedObjectID: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSManagedObjectID
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .objectIDAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .objectIDAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSManagedObjectID>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -434,12 +440,19 @@ extension NSNull: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSNull
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .undefinedAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .undefinedAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
return self.init()
|
||||
func forceCast<T: NSNull>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
}
|
||||
return forceCast(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
@@ -464,7 +477,6 @@ extension NSNumber: QueryableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSNumber>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -486,12 +498,14 @@ extension NSString: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSString
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .stringAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSString>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -513,10 +527,13 @@ extension NSURL: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSString
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .stringAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
return self.init(string: value as String)
|
||||
}
|
||||
@@ -535,10 +552,13 @@ extension NSUUID: QueryableAttributeType {
|
||||
|
||||
public typealias QueryableNativeType = NSString
|
||||
|
||||
public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType
|
||||
public class var cs_rawAttributeType: NSAttributeType {
|
||||
|
||||
return .stringAttributeType
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
return self.init(uuidString: value.lowercased)
|
||||
}
|
||||
@@ -568,7 +588,7 @@ extension String: QueryableAttributeType {
|
||||
@inline(__always)
|
||||
public func cs_toQueryableNativeType() -> QueryableNativeType {
|
||||
|
||||
return self as NSString
|
||||
return self as QueryableNativeType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public protocol QueryableSource: class {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U?
|
||||
func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U?
|
||||
|
||||
/**
|
||||
Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
@@ -56,7 +56,7 @@ public protocol QueryableSource: class {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U?
|
||||
func queryValue<T, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U?
|
||||
|
||||
/**
|
||||
Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
@@ -68,7 +68,7 @@ public protocol QueryableSource: class {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]?
|
||||
func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]?
|
||||
|
||||
/**
|
||||
Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
@@ -80,7 +80,7 @@ public protocol QueryableSource: class {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]?
|
||||
func queryAttributes<T>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]?
|
||||
|
||||
/**
|
||||
The internal `NSManagedObjectContext` managed by this `QueryableSource`. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
|
||||
|
||||
@@ -92,10 +92,23 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { nil },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,10 +126,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,10 +161,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,10 +196,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,64 +234,74 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: RelationshipProtocol
|
||||
|
||||
public let keyPath: KeyPath
|
||||
public let keyPath: RawKeyPath
|
||||
|
||||
internal let isToMany = false
|
||||
internal let isOrdered = false
|
||||
internal let deleteRule: NSDeleteRule
|
||||
internal let minCount: Int = 0
|
||||
internal let maxCount: Int = 1
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||
internal let versionHashModifier: String?
|
||||
internal let renamingIdentifier: String?
|
||||
|
||||
internal var parentObject: () -> CoreStoreObject = {
|
||||
|
||||
CoreStore.abort("Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types.")
|
||||
}
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?)
|
||||
internal let versionHashModifier: () -> String?
|
||||
internal let renamingIdentifier: () -> String?
|
||||
internal let affectedByKeyPaths: () -> Set<String>
|
||||
internal weak var parentObject: CoreStoreObject?
|
||||
|
||||
internal var nativeValue: NSManagedObject? {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { $0 as! NSManagedObject? }
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { $0 as! NSManagedObject? }
|
||||
)
|
||||
}
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||
private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, versionHashModifier: @autoclosure @escaping () -> String?, renamingIdentifier: @autoclosure @escaping () -> String?, affectedByKeyPaths: @autoclosure @escaping () -> Set<String>) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.deleteRule = deleteRule.nativeValue
|
||||
self.inverse = (D.self, inverseKeyPath)
|
||||
self.versionHashModifier = versionHashModifier
|
||||
self.renamingIdentifier = renamingIdentifier
|
||||
self.affectedByKeyPaths = affectedByKeyPaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,10 +338,27 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { nil }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { nil },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -296,10 +378,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,10 +419,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,10 +460,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, minCount: minCount, maxCount: maxCount, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,7 +502,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: RelationshipProtocol
|
||||
|
||||
public let keyPath: KeyPath
|
||||
public let keyPath: RawKeyPath
|
||||
|
||||
internal let isToMany = true
|
||||
internal let isOptional = true
|
||||
@@ -374,51 +510,60 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
internal let deleteRule: NSDeleteRule
|
||||
internal let minCount: Int
|
||||
internal let maxCount: Int
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||
internal let versionHashModifier: String?
|
||||
internal let renamingIdentifier: String?
|
||||
|
||||
internal var parentObject: () -> CoreStoreObject = {
|
||||
|
||||
CoreStore.abort("Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types.")
|
||||
}
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?)
|
||||
internal let versionHashModifier: () -> String?
|
||||
internal let renamingIdentifier: () -> String?
|
||||
internal let affectedByKeyPaths: () -> Set<String>
|
||||
internal weak var parentObject: CoreStoreObject?
|
||||
|
||||
internal var nativeValue: NSOrderedSet {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSOrderedSet?) ?? [] }
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSOrderedSet?) ?? [] }
|
||||
)
|
||||
}
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyPath: String, minCount: Int, maxCount: Int, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||
private init(keyPath: String, minCount: Int, maxCount: Int, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, versionHashModifier: @autoclosure @escaping () -> String?, renamingIdentifier: @autoclosure @escaping () -> String?, affectedByKeyPaths: @autoclosure @escaping () -> Set<String>) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.deleteRule = deleteRule.nativeValue
|
||||
@@ -429,6 +574,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
let range = (Swift.max(0, minCount) ... maxCount)
|
||||
self.minCount = range.lowerBound
|
||||
self.maxCount = range.upperBound
|
||||
self.affectedByKeyPaths = affectedByKeyPaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,10 +612,27 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { nil },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,10 +652,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,10 +693,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -535,10 +734,28 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
- parameter deleteRule: defines what happens to relationship when an object is deleted. Valid values are `.nullify`, `.cascade`, and `.delete`. Defaults to `.nullify`.
|
||||
- parameter versionHashModifier: used to mark or denote a relationship 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 renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier 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 name.
|
||||
- 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 convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
public convenience init(
|
||||
_ keyPath: RawKeyPath,
|
||||
inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>,
|
||||
deleteRule: DeleteRule = .nullify,
|
||||
minCount: Int = 0,
|
||||
maxCount: Int = 0,
|
||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||
renamingIdentifier: @autoclosure @escaping () -> String? = nil,
|
||||
affectedByKeyPaths: @autoclosure @escaping () -> Set<String> = []) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
self.init(
|
||||
keyPath: keyPath,
|
||||
inverseKeyPath: { inverse(D.meta).keyPath },
|
||||
deleteRule: deleteRule,
|
||||
minCount: minCount,
|
||||
maxCount: maxCount,
|
||||
versionHashModifier: versionHashModifier,
|
||||
renamingIdentifier: renamingIdentifier,
|
||||
affectedByKeyPaths: affectedByKeyPaths
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -559,7 +776,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: RelationshipProtocol
|
||||
|
||||
public let keyPath: KeyPath
|
||||
public let keyPath: RawKeyPath
|
||||
|
||||
internal let isToMany = true
|
||||
internal let isOptional = true
|
||||
@@ -567,51 +784,60 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
internal let deleteRule: NSDeleteRule
|
||||
internal let minCount: Int
|
||||
internal let maxCount: Int
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||
internal let versionHashModifier: String?
|
||||
internal let renamingIdentifier: String?
|
||||
|
||||
internal var parentObject: () -> CoreStoreObject = {
|
||||
|
||||
CoreStore.abort("Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types.")
|
||||
}
|
||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?)
|
||||
internal let versionHashModifier: () -> String?
|
||||
internal let renamingIdentifier: () -> String?
|
||||
internal let affectedByKeyPaths: () -> Set<String>
|
||||
internal weak var parentObject: CoreStoreObject?
|
||||
|
||||
internal var nativeValue: NSSet {
|
||||
|
||||
get {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSSet?) ?? [] }
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return object.rawObject!.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
didGetValue: { ($0 as! NSSet?) ?? [] }
|
||||
)
|
||||
}
|
||||
}
|
||||
set {
|
||||
|
||||
let object = self.parentObject() as! O
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
self.parentObject != nil,
|
||||
"Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return withExtendedLifetime(self.parentObject! as! O) { (object: O) in
|
||||
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
object.rawObject!.isEditableInContext() == true,
|
||||
"Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction."
|
||||
)
|
||||
object.rawObject!.setValue(
|
||||
newValue,
|
||||
forKvcKey: self.keyPath
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||
private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: @autoclosure @escaping () -> String?, renamingIdentifier: @autoclosure @escaping () -> String?, affectedByKeyPaths: @autoclosure @escaping () -> Set<String>) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.deleteRule = deleteRule.nativeValue
|
||||
@@ -622,6 +848,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
let range = (Swift.max(0, minCount) ... maxCount)
|
||||
self.minCount = range.lowerBound
|
||||
self.maxCount = range.upperBound
|
||||
self.affectedByKeyPaths = affectedByKeyPaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,8 +884,8 @@ extension RelationshipContainer.ToManyOrdered: RandomAccessCollection {
|
||||
|
||||
public func makeIterator() -> Iterator {
|
||||
|
||||
let iterator = self.nativeValue.makeIterator()
|
||||
return AnyIterator({ D.cs_fromRaw(object: iterator.next() as! NSManagedObject) })
|
||||
var iterator = self.nativeValue.makeIterator()
|
||||
return AnyIterator({ iterator.next().flatMap({ D.cs_fromRaw(object: $0 as! NSManagedObject) }) })
|
||||
}
|
||||
|
||||
|
||||
@@ -712,8 +939,8 @@ extension RelationshipContainer.ToManyUnordered: Sequence {
|
||||
|
||||
public func makeIterator() -> Iterator {
|
||||
|
||||
let iterator = self.nativeValue.makeIterator()
|
||||
return AnyIterator({ D.cs_fromRaw(object: iterator.next() as! NSManagedObject) })
|
||||
var iterator = self.nativeValue.makeIterator()
|
||||
return AnyIterator({ iterator.next().flatMap({ D.cs_fromRaw(object: $0 as! NSManagedObject) }) })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,7 +977,7 @@ extension RelationshipContainer.ToOne {
|
||||
dog.master.value = anotherDog.master.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) {
|
||||
public static func .= <O2>(_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) {
|
||||
|
||||
relationship.nativeValue = relationship2.nativeValue
|
||||
}
|
||||
@@ -795,7 +1022,7 @@ extension RelationshipContainer.ToOne {
|
||||
if dog.master.value == person { ... }
|
||||
```
|
||||
*/
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) -> Bool {
|
||||
public static func .== <O2>(_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) -> Bool {
|
||||
|
||||
return relationship.nativeValue == relationship2.nativeValue
|
||||
}
|
||||
@@ -828,7 +1055,7 @@ extension RelationshipContainer.ToManyOrdered {
|
||||
person.pets.value = anotherPerson.pets.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
public static func .= <O2>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
|
||||
relationship.nativeValue = relationship2.nativeValue
|
||||
}
|
||||
@@ -879,7 +1106,7 @@ extension RelationshipContainer.ToManyOrdered {
|
||||
if person.pets.value == anotherPerson.pets.value { ... }
|
||||
```
|
||||
*/
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) -> Bool {
|
||||
public static func .== <O2>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) -> Bool {
|
||||
|
||||
return relationship.nativeValue == relationship2.nativeValue
|
||||
}
|
||||
@@ -912,7 +1139,7 @@ extension RelationshipContainer.ToManyUnordered {
|
||||
person.pets.value = anotherPerson.pets.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) {
|
||||
public static func .= <O2>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) {
|
||||
|
||||
relationship.nativeValue = relationship2.nativeValue
|
||||
}
|
||||
@@ -927,7 +1154,7 @@ extension RelationshipContainer.ToManyUnordered {
|
||||
person.pets.value = anotherPerson.pets.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
public static func .= <O2>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
|
||||
relationship.nativeValue = NSSet(set: relationship2.nativeValue.set)
|
||||
}
|
||||
@@ -972,25 +1199,8 @@ extension RelationshipContainer.ToManyUnordered {
|
||||
if person.pets.value == anotherPerson.pets.value { ... }
|
||||
```
|
||||
*/
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) -> Bool {
|
||||
public static func .== <O2>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) -> Bool {
|
||||
|
||||
return relationship.nativeValue.isEqual(relationship2.nativeValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipProtocol
|
||||
|
||||
internal protocol RelationshipProtocol: class {
|
||||
|
||||
var keyPath: KeyPath { get }
|
||||
var isToMany: Bool { get }
|
||||
var isOrdered: Bool { get }
|
||||
var deleteRule: NSDeleteRule { get }
|
||||
var inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) { get }
|
||||
var parentObject: () -> CoreStoreObject { get set }
|
||||
var versionHashModifier: String? { get }
|
||||
var renamingIdentifier: String? { get }
|
||||
var minCount: Int { get }
|
||||
var maxCount: Int { get }
|
||||
}
|
||||
|
||||
45
Sources/RelationshipProtocol.swift
Normal file
45
Sources/RelationshipProtocol.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// RelationshipProtocol.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - RelationshipProtocol
|
||||
|
||||
internal protocol RelationshipProtocol: class {
|
||||
|
||||
var keyPath: RawKeyPath { get }
|
||||
var isToMany: Bool { get }
|
||||
var isOrdered: Bool { get }
|
||||
var deleteRule: NSDeleteRule { get }
|
||||
var inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) { get }
|
||||
var affectedByKeyPaths: () -> Set<String> { get }
|
||||
weak var parentObject: CoreStoreObject? { get set }
|
||||
var versionHashModifier: () -> String? { get }
|
||||
var renamingIdentifier: () -> String? { get }
|
||||
var minCount: Int { get }
|
||||
var maxCount: Int { get }
|
||||
}
|
||||
@@ -117,6 +117,20 @@ public final class SQLiteStore: LocalStorage {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Queries the file size (in bytes) of the store, or `nil` if the file does not exist yet
|
||||
*/
|
||||
public func fileSize() -> UInt64? {
|
||||
|
||||
guard let attribute = try? FileManager.default.attributesOfItem(atPath: self.fileURL.path),
|
||||
let sizeAttribute = attribute[.size],
|
||||
let fileSize = sizeAttribute as? NSNumber else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return fileSize.uint64Value
|
||||
}
|
||||
|
||||
|
||||
// MARK: StorageInterface
|
||||
|
||||
@@ -191,13 +205,27 @@ public final class SQLiteStore: LocalStorage {
|
||||
return storeOptions
|
||||
}
|
||||
|
||||
/**
|
||||
Called by the `DataStack` to perform checkpoint operations on the storage. For `SQLiteStore`, this converts the database's WAL journaling mode to DELETE to force a checkpoint.
|
||||
*/
|
||||
public func cs_finalizeStorageAndWait(soureModelHint: NSManagedObjectModel) throws {
|
||||
|
||||
_ = try withExtendedLifetime(NSPersistentStoreCoordinator(managedObjectModel: soureModelHint)) { (coordinator: NSPersistentStoreCoordinator) in
|
||||
|
||||
try coordinator.addPersistentStore(
|
||||
ofType: type(of: self).storeType,
|
||||
configurationName: self.configuration,
|
||||
at: fileURL,
|
||||
options: [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Called by the `DataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `SQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
|
||||
*/
|
||||
public func cs_eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws {
|
||||
|
||||
// TODO: check if attached to persistent store
|
||||
|
||||
func deleteFiles(storeURL: URL, extraFiles: [String] = []) throws {
|
||||
|
||||
let fileManager = FileManager.default
|
||||
|
||||
@@ -47,7 +47,7 @@ public struct SectionBy {
|
||||
|
||||
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||
*/
|
||||
public init(_ sectionKeyPath: KeyPath) {
|
||||
public init(_ sectionKeyPath: RawKeyPath) {
|
||||
|
||||
self.init(sectionKeyPath, { $0 })
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public struct SectionBy {
|
||||
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||
*/
|
||||
public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
|
||||
public init(_ sectionKeyPath: RawKeyPath, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
|
||||
|
||||
self.sectionKeyPath = sectionKeyPath
|
||||
self.sectionIndexTransformer = sectionIndexTransformer
|
||||
@@ -68,6 +68,6 @@ public struct SectionBy {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let sectionKeyPath: KeyPath
|
||||
internal let sectionKeyPath: RawKeyPath
|
||||
internal let sectionIndexTransformer: (_ sectionName: String?) -> String?
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter keyPath: the attribute name
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying an entity attribute
|
||||
*/
|
||||
public static func attribute(_ keyPath: KeyPath) -> SelectTerm {
|
||||
public static func attribute(_ keyPath: RawKeyPath) -> SelectTerm {
|
||||
|
||||
return ._attribute(keyPath)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average(<attributeName>)" is used
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying the average value of an attribute
|
||||
*/
|
||||
public static func average(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
|
||||
public static func average(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm {
|
||||
|
||||
return ._aggregate(
|
||||
function: "average:",
|
||||
@@ -113,7 +113,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count(<attributeName>)" is used
|
||||
- returns: a `SelectTerm` to a `Select` clause for a count query
|
||||
*/
|
||||
public static func count(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
|
||||
public static func count(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm {
|
||||
|
||||
return ._aggregate(
|
||||
function: "count:",
|
||||
@@ -135,7 +135,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max(<attributeName>)" is used
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying the maximum value for an attribute
|
||||
*/
|
||||
public static func maximum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
|
||||
public static func maximum(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm {
|
||||
|
||||
return ._aggregate(
|
||||
function: "max:",
|
||||
@@ -157,7 +157,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min(<attributeName>)" is used
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying the minimum value for an attribute
|
||||
*/
|
||||
public static func minimum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
|
||||
public static func minimum(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm {
|
||||
|
||||
return ._aggregate(
|
||||
function: "min:",
|
||||
@@ -179,7 +179,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum(<attributeName>)" is used
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
|
||||
*/
|
||||
public static func sum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
|
||||
public static func sum(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm {
|
||||
|
||||
return ._aggregate(
|
||||
function: "sum:",
|
||||
@@ -202,7 +202,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used
|
||||
- returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
|
||||
*/
|
||||
public static func objectID(as alias: KeyPath? = nil) -> SelectTerm {
|
||||
public static func objectID(as alias: RawKeyPath? = nil) -> SelectTerm {
|
||||
|
||||
return ._identity(
|
||||
alias: alias ?? "objectID",
|
||||
@@ -213,17 +213,17 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
|
||||
// MARK: ExpressibleByStringLiteral
|
||||
|
||||
public init(stringLiteral value: KeyPath) {
|
||||
public init(stringLiteral value: RawKeyPath) {
|
||||
|
||||
self = ._attribute(value)
|
||||
}
|
||||
|
||||
public init(unicodeScalarLiteral value: KeyPath) {
|
||||
public init(unicodeScalarLiteral value: RawKeyPath) {
|
||||
|
||||
self = ._attribute(value)
|
||||
}
|
||||
|
||||
public init(extendedGraphemeClusterLiteral value: KeyPath) {
|
||||
public init(extendedGraphemeClusterLiteral value: RawKeyPath) {
|
||||
|
||||
self = ._attribute(value)
|
||||
}
|
||||
@@ -274,8 +274,8 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
case _attribute(KeyPath)
|
||||
case _aggregate(function: String, keyPath: KeyPath, alias: String, nativeType: NSAttributeType)
|
||||
case _attribute(RawKeyPath)
|
||||
case _aggregate(function: String, keyPath: RawKeyPath, alias: String, nativeType: NSAttributeType)
|
||||
case _identity(alias: String, nativeType: NSAttributeType)
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ public struct Select<T: SelectResultType>: Hashable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == <T: SelectResultType, U: SelectResultType>(lhs: Select<T>, rhs: Select<U>) -> Bool {
|
||||
public static func == <T, U>(lhs: Select<T>, rhs: Select<U>) -> Bool {
|
||||
|
||||
return lhs.selectTerms == rhs.selectTerms
|
||||
}
|
||||
@@ -401,13 +401,14 @@ internal extension Collection where Iterator.Element == SelectTerm {
|
||||
return entity.attributesByName[components[0]]
|
||||
|
||||
default:
|
||||
guard let relationship = entity.relationshipsByName[components[0]] else {
|
||||
|
||||
return nil
|
||||
guard let relationship = entity.relationshipsByName[components[0]],
|
||||
let destinationEntity = relationship.destinationEntity else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return attributeDescription(
|
||||
for: components.dropFirst().joined(separator: "."),
|
||||
in: relationship.entity
|
||||
in: destinationEntity
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -418,18 +419,7 @@ internal extension Collection where Iterator.Element == SelectTerm {
|
||||
switch term {
|
||||
|
||||
case ._attribute(let keyPath):
|
||||
let entityDescription = fetchRequest.entity!
|
||||
if let attributeDescription = attributeDescription(for: keyPath, in: entityDescription) {
|
||||
|
||||
propertiesToFetch.append(attributeDescription)
|
||||
}
|
||||
else {
|
||||
|
||||
CoreStore.log(
|
||||
.warning,
|
||||
message: "The key path \"\(keyPath)\" could not be resolved in entity \(cs_typeName(entityDescription.managedObjectClassName)) as an attribute and will be ignored by \(cs_typeName(owner)) query clause."
|
||||
)
|
||||
}
|
||||
propertiesToFetch.append(keyPath)
|
||||
|
||||
case ._aggregate(let function, let keyPath, let alias, let nativeType):
|
||||
let entityDescription = fetchRequest.entity!
|
||||
@@ -479,7 +469,7 @@ internal extension Collection where Iterator.Element == SelectTerm {
|
||||
fetchRequest.propertiesToFetch = propertiesToFetch
|
||||
}
|
||||
|
||||
internal func keyPathForFirstSelectTerm() -> KeyPath {
|
||||
internal func keyPathForFirstSelectTerm() -> RawKeyPath {
|
||||
|
||||
switch self.first! {
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ public enum SetupResult<T: StorageInterface>: Hashable {
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == <T: StorageInterface, U: StorageInterface>(lhs: SetupResult<T>, rhs: SetupResult<U>) -> Bool {
|
||||
public static func == <T, U>(lhs: SetupResult<T>, rhs: SetupResult<U>) -> Bool {
|
||||
|
||||
switch (lhs, rhs) {
|
||||
|
||||
|
||||
@@ -141,6 +141,11 @@ public protocol LocalStorage: StorageInterface {
|
||||
*/
|
||||
func dictionary(forOptions options: LocalStorageOptions) -> [AnyHashable: Any]?
|
||||
|
||||
/**
|
||||
Called by the `DataStack` to perform checkpoint operations on the storage. (SQLite stores for example, can convert the database's WAL journaling mode to DELETE to force a checkpoint)
|
||||
*/
|
||||
func cs_finalizeStorageAndWait(soureModelHint: NSManagedObjectModel) throws
|
||||
|
||||
/**
|
||||
Called by the `DataStack` to perform actual deletion of the store file from disk. **Do not call directly!** The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (SQLite stores for example, can convert WAL journaling mode to DELETE before deleting)
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user