mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-07-18 18:51:19 +02:00
Compare commits
282 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b9fddad6a | |||
| fbe7bd7bf8 | |||
| 15edabdbb5 | |||
| f447bcfb95 | |||
| 15e5e4fdf6 | |||
| 583c6b7249 | |||
| 18b933957e | |||
| 2c7039232e | |||
| d3b3b5ff4a | |||
| d90e8d1303 | |||
| b55dd13dff | |||
| 66dd5b6f27 | |||
| 49c4b770eb | |||
| 662aaa1e75 | |||
| dd4e47d7f9 | |||
| 9ea5073bc8 | |||
| e314db8f56 | |||
| 48d936d068 | |||
| b2ff8a15ef | |||
| 8a4d1cd7c6 | |||
| 8ce26c213d | |||
| f3816b9abf | |||
| 21961780d4 | |||
| 305e2b61a0 | |||
| 0430f66240 | |||
| 65772edd00 | |||
| 02d7870d75 | |||
| aca1709e13 | |||
| b6ee0b014f | |||
| e37186da73 | |||
| 588fa35c84 | |||
| f6614cda66 | |||
| 639574d8c2 | |||
| 094703155c | |||
| 6dd254e713 | |||
| 204025721c | |||
| 27ffc1d225 | |||
| ba6f0c39d5 | |||
| ab2eac8f6c | |||
| f460a0b30f | |||
| 50bc3ace06 | |||
| d2ddf2002f | |||
| b4117eeb02 | |||
| 106275b2dd | |||
| 08d9298be0 | |||
| ff0c4d94fc | |||
| 50e50c0613 | |||
| 5c8a0e425b | |||
| 03b71caf7e | |||
| 7ff29d6086 | |||
| 8d86425875 | |||
| 97242d9726 | |||
| 780ff4e60b | |||
| 11743dfb5f | |||
| 9eaf85388c | |||
| 06635c9d2f | |||
| 1d2eef7894 | |||
| 85ed815ec2 | |||
| 096e5493a6 | |||
| 0aa8c03424 | |||
| 4ead3c34dd | |||
| 645034dde5 | |||
| 85706a3c57 | |||
| c5ae4606b9 | |||
| fa682215c5 | |||
| e814733ae9 | |||
| e2236698fa | |||
| be5da632b3 | |||
| dc73cd6dd9 | |||
| 7beb3bec75 | |||
| 53100b202d | |||
| cc84b1f8bd | |||
| 474f52ed2b | |||
| 16225fc4c6 | |||
| 03bb7619da | |||
| 1bfb7451c3 | |||
| 3e082d5ed4 | |||
| e45d67252c | |||
| 3d427c29c4 | |||
| 1068517b94 | |||
| 0d23ce1598 | |||
| fd1ce20863 | |||
| 2c5fa63f40 | |||
| 78e43a37a5 | |||
| fde85a9743 | |||
| dbbc0adae5 | |||
| 2a62770552 | |||
| f436b26e8e | |||
| c566226747 | |||
| cd405e038e | |||
| 92a37053b0 | |||
| 0b57cff27d | |||
| 3ebc44b546 | |||
| 68f1027ba7 | |||
| 005729be85 | |||
| 8bac4aa901 | |||
| da170c7e51 | |||
| 211e69023e | |||
| 2912dcf010 | |||
| 3e00a3da06 | |||
| a33e248828 | |||
| 75e14fbbed | |||
| 9922deac4d | |||
| 86be046c9f | |||
| 0f10bc3349 | |||
| 9685f0aef2 | |||
| 1e51000155 | |||
| 3bd459bb1a | |||
| c89bc3c227 | |||
| 0f405a50aa | |||
| f5e1643ef7 | |||
| f62137fb58 | |||
| 37fbedd799 | |||
| 28b43f33fa | |||
| 81a72f29ea | |||
| f7aaf4fb2a | |||
| a52acf2ebd | |||
| 74c64619c3 | |||
| 4a5bc6450b | |||
| fe69e7c6c4 | |||
| ccf7c62aad | |||
| f36cb8af63 | |||
| 10ccadd96c | |||
| 5c0e78bd53 | |||
| 8a09688117 | |||
| a366bcf1a3 | |||
| fcd4be9011 | |||
| 535eb76adc | |||
| c6e68ac24f | |||
| aff966aac9 | |||
| 32743b3aee | |||
| a20ad87583 | |||
| a11915db12 | |||
| 961f39a806 | |||
| 3096cb784c | |||
| 809aa4ff96 | |||
| 8d926d25ec | |||
| 790454f514 | |||
| 9a38707c58 | |||
| fb7e2f7f7f | |||
| f72efc80b2 | |||
| fcda5399da | |||
| fd3a9b00ec | |||
| f56c37f9ee | |||
| 5f5000218a | |||
| e8eb309d82 | |||
| d0c3203e63 | |||
| f5b3901caa | |||
| 1a99fea820 | |||
| 195b60615b | |||
| 2c394965b8 | |||
| 746d697691 | |||
| 5689158b43 | |||
| 6fcdf3d011 | |||
| e26573c18e | |||
| 801cf8d9f0 | |||
| eced8f2e93 | |||
| 3b735d07ec | |||
| 5eb5476e3a | |||
| 6a42a0054e | |||
| 8c437e19b8 | |||
| 9cd3b6c879 | |||
| fe135acbec | |||
| 997c5bdcfa | |||
| 23e12c4539 | |||
| ca9798be14 | |||
| 6e01a58c85 | |||
| 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 | |||
| ef0937fec4 | |||
| 35885b40de | |||
| d669569196 | |||
| ae919ff3c8 | |||
| 1a7a4690d1 | |||
| b9b96d1a35 | |||
| da3a9590ac | |||
| 6b3d75bea1 | |||
| d44721fef0 | |||
| 3f268e8376 | |||
| 303fea4ebe | |||
| 77173cdad0 | |||
| 1e24a7d739 | |||
| a3b33bedb8 | |||
| eaf7544c50 | |||
| 67863120e0 | |||
| 1b0e305d9a | |||
| 91fda01071 | |||
| feb0e30735 | |||
| 9c25336ff6 | |||
| 66bef87422 | |||
| dd2949ee18 | |||
| e0abb9b0af | |||
| 42c28b064a | |||
| 0b097b8c85 | |||
| fce5d2f301 | |||
| 8ff163af30 | |||
| 19abedfa9f | |||
| 48828fdca3 | |||
| 9d65a27557 | |||
| 6d04806608 | |||
| 54129f7362 | |||
| 54c81d23f5 | |||
| 53ab140341 | |||
| 9dc4331b26 | |||
| e6aa72fb5f | |||
| 274a54451a | |||
| fe70b7a27d | |||
| 02a660e4a6 | |||
| a543a4c94a | |||
| fd14a18248 | |||
| b0e2655bdf | |||
| b6bc7c2edf | |||
| 1938f0d9de | |||
| 94e6db669f | |||
| b1972b82f1 | |||
| 5ffaca1375 | |||
| a73306fecb | |||
| 9f3db61ff7 | |||
| e5ef4992d3 | |||
| c0ae129b22 | |||
| 4aa1a63f9a | |||
| 4fc10afe1e | |||
| 8b77e4e5a0 | |||
| 258c237100 | |||
| 6948db516d | |||
| b5d80fd272 | |||
| cdcd7d0416 | |||
| a5162239d5 | |||
| 1ad6ac5769 | |||
| ecb3d0cfa0 | |||
| 81355fd9c5 | |||
| 97d7a276fe | |||
| d72d1afe8b | |||
| 716e069984 | |||
| 881ee4af0a | |||
| acc0ce1c32 | |||
| b97f6d6a0a | |||
| 818abfc1a1 | |||
| f055c54a66 | |||
| cb6d5b015b | |||
| 494965de23 | |||
| fe25a9aa36 | |||
| f21e4e12e0 | |||
| 92890d1e1d | |||
| 0c483e0e19 | |||
| 6055685c00 | |||
| ee71442b08 | |||
| 341ec5e771 | |||
| 8569c3c524 | |||
| 3224fcf71d | |||
| 9ff1c9d545 | |||
| c40d17a6ad | |||
| 9d5e04854a | |||
| d2fd03c1f0 | |||
| 7baaee493d | |||
| 03973790a8 | |||
| 7ee027f44d |
@@ -0,0 +1,2 @@
|
|||||||
|
try:
|
||||||
|
project: 'CoreStore.xcworkspace'
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
3.0.1
|
4.0
|
||||||
|
|||||||
+21
-15
@@ -1,5 +1,5 @@
|
|||||||
language: objective-c
|
language: objective-c
|
||||||
osx_image: xcode8.2
|
osx_image: xcode9
|
||||||
sudo: false
|
sudo: false
|
||||||
git:
|
git:
|
||||||
submodules: false
|
submodules: false
|
||||||
@@ -10,23 +10,29 @@ env:
|
|||||||
- LC_CTYPE=en_US.UTF-8
|
- LC_CTYPE=en_US.UTF-8
|
||||||
- LANG=en_US.UTF-8
|
- LANG=en_US.UTF-8
|
||||||
matrix:
|
matrix:
|
||||||
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
- DESTINATION="OS=11.0,name=iPhone 8" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||||
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 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=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 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=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 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.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 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 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 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="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 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=3.1,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.1 RUN_TESTS="NO" POD_LINT="NO"
|
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
|
||||||
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.1 RUN_TESTS="NO" POD_LINT="NO"
|
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.13 RUN_TESTS="YES" POD_LINT="NO"
|
||||||
- DESTINATION="OS=10.1,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.1 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=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.1 RUN_TESTS="YES" 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:
|
before_install:
|
||||||
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
|
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
|
||||||
- gem install xcpretty --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.18/Carthage.pkg"
|
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.26.0/Carthage.pkg"
|
||||||
- sudo installer -pkg "Carthage.pkg" -target /
|
- sudo installer -pkg "Carthage.pkg" -target /
|
||||||
- rm "Carthage.pkg"
|
- rm "Carthage.pkg"
|
||||||
|
- npm install ios-sim -g
|
||||||
|
- ios-sim start --devicetypeid "com.apple.CoreSimulator.SimDeviceType.iPhone-8, 11.0"
|
||||||
before_script:
|
before_script:
|
||||||
- carthage update --use-submodules
|
- carthage update --use-submodules
|
||||||
script:
|
script:
|
||||||
@@ -37,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 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;
|
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||||
fi
|
fi
|
||||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.2" -destination "OS=10.1,name=iPhone 7" -configuration Debug 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 "CoreStore iOS" -sdk "iphonesimulator10.2" -destination "OS=10.1,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 Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
|
||||||
- if [ $POD_LINT == "YES" ]; then
|
- if [ $POD_LINT == "YES" ]; then
|
||||||
pod lib lint --quick;
|
pod lib lint --quick;
|
||||||
fi
|
fi
|
||||||
|
|||||||
+2
-4
@@ -1,6 +1,6 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "CoreStore"
|
s.name = "CoreStore"
|
||||||
s.version = "3.0.2"
|
s.version = "5.0.0"
|
||||||
s.license = "MIT"
|
s.license = "MIT"
|
||||||
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
|
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
|
||||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||||
@@ -16,7 +16,5 @@ Pod::Spec.new do |s|
|
|||||||
s.public_header_files = "Sources/**/*.h"
|
s.public_header_files = "Sources/**/*.h"
|
||||||
s.frameworks = "Foundation", "CoreData"
|
s.frameworks = "Foundation", "CoreData"
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D USE_FRAMEWORKS -D DEBUG',
|
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG' }
|
||||||
'OTHER_SWIFT_FLAGS[config=Release]' => '-D USE_FRAMEWORKS',
|
|
||||||
'GCC_PREPROCESSOR_DEFINITIONS' => 'USE_FRAMEWORKS=1' }
|
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0800"
|
LastUpgradeVersion = "0900"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0800"
|
LastUpgradeVersion = "0900"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
@@ -63,12 +64,18 @@
|
|||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
<AdditionalOptions>
|
||||||
|
<AdditionalOption
|
||||||
|
key = "NSZombieEnabled"
|
||||||
|
value = "YES"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</AdditionalOption>
|
||||||
</AdditionalOptions>
|
</AdditionalOptions>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0800"
|
LastUpgradeVersion = "0900"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0800"
|
LastUpgradeVersion = "0900"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
</Testables>
|
</Testables>
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
|
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
|
||||||
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */; };
|
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */; };
|
||||||
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */; };
|
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */; };
|
||||||
B5125C141B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */; };
|
|
||||||
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977D81B120B80003D50A5 /* ObserversViewController.swift */; };
|
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977D81B120B80003D50A5 /* ObserversViewController.swift */; };
|
||||||
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */; };
|
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */; };
|
||||||
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977DE1B120F83003D50A5 /* MapKit.framework */; };
|
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977DE1B120F83003D50A5 /* MapKit.framework */; };
|
||||||
@@ -266,12 +265,12 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0700;
|
LastSwiftUpdateCheck = 0700;
|
||||||
LastUpgradeCheck = 0800;
|
LastUpgradeCheck = 0900;
|
||||||
ORGANIZATIONNAME = "John Rommel Estropia";
|
ORGANIZATIONNAME = "John Rommel Estropia";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
B54AAD481AF4D26E00848AE0 = {
|
B54AAD481AF4D26E00848AE0 = {
|
||||||
CreatedOnToolsVersion = 6.3;
|
CreatedOnToolsVersion = 6.3;
|
||||||
LastSwiftMigration = 0800;
|
LastSwiftMigration = 0900;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -331,7 +330,6 @@
|
|||||||
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
|
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
|
||||||
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
|
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
|
||||||
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
|
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
|
||||||
B5125C141B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel in Sources */,
|
|
||||||
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
|
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
|
||||||
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
|
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
|
||||||
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
|
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
|
||||||
@@ -373,13 +371,21 @@
|
|||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
@@ -407,6 +413,8 @@
|
|||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -418,13 +426,21 @@
|
|||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
@@ -443,6 +459,8 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -456,7 +474,8 @@
|
|||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -470,7 +489,8 @@
|
|||||||
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0800"
|
LastUpgradeVersion = "0900"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
</Testables>
|
</Testables>
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
|
||||||
|
|
||||||
application.statusBarStyle = .lightContent
|
application.statusBarStyle = .lightContent
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10112" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="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>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10083"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<customFonts key="customFonts">
|
<customFonts key="customFonts">
|
||||||
<mutableArray key="AppleSDGothicNeo.ttc">
|
<array key="AppleSDGothicNeo.ttc">
|
||||||
<string>AppleSDGothicNeo-Regular</string>
|
<string>AppleSDGothicNeo-Regular</string>
|
||||||
</mutableArray>
|
</array>
|
||||||
<mutableArray key="HelveticaNeue.ttc">
|
<array key="HelveticaNeue.ttc">
|
||||||
<string>HelveticaNeue-Bold</string>
|
|
||||||
<string>HelveticaNeue-Bold</string>
|
|
||||||
<string>HelveticaNeue</string>
|
<string>HelveticaNeue</string>
|
||||||
<string>HelveticaNeue</string>
|
<string>HelveticaNeue-Bold</string>
|
||||||
</mutableArray>
|
</array>
|
||||||
<mutableArray key="HelveticaNeueLights.ttc">
|
<array key="HelveticaNeueLights.ttc">
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
<string>HelveticaNeue-Light</string>
|
||||||
<string>HelveticaNeue-Thin</string>
|
<string>HelveticaNeue-Thin</string>
|
||||||
<string>HelveticaNeue-Light</string>
|
</array>
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
<string>HelveticaNeue-Light</string>
|
|
||||||
</mutableArray>
|
|
||||||
</customFonts>
|
</customFonts>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--SNS Accounts-->
|
<!--SNS Accounts-->
|
||||||
@@ -41,34 +30,34 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="AW4-lY-JNk" customClass="StackSetupDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="AW4-lY-JNk" customClass="StackSetupDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="S3A-lm-AuA">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="S3A-lm-AuA">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<view key="tableHeaderView" contentMode="scaleToFill" id="yud-WH-MPa">
|
<view key="tableHeaderView" contentMode="scaleToFill" id="yud-WH-MPa">
|
||||||
<rect key="frame" x="0.0" y="64" width="600" height="150"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="150"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sns" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="czc-nd-es9">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sns" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="czc-nd-es9">
|
||||||
<rect key="frame" x="20" y="20" width="560" height="26.5"/>
|
<rect key="frame" x="20" y="20" width="335" height="26.5"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
||||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="name" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1eh-91-O2N">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="name" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1eh-91-O2N">
|
||||||
<rect key="frame" x="20" y="70" width="41" height="20.5"/>
|
<rect key="frame" x="20" y="70" width="41" height="20.5"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
||||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="friends" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p2y-0T-hQs">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="friends" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p2y-0T-hQs">
|
||||||
<rect key="frame" x="539.5" y="72" width="40.5" height="17"/>
|
<rect key="frame" x="314.5" y="72" width="40.5" height="17"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="14"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="14"/>
|
||||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="0.20392156862745098" green="0.28627450980392155" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="1eh-91-O2N" firstAttribute="top" secondItem="czc-nd-es9" secondAttribute="bottom" constant="23.5" id="F6q-Jt-glI"/>
|
<constraint firstItem="1eh-91-O2N" firstAttribute="top" secondItem="czc-nd-es9" secondAttribute="bottom" constant="23.5" id="F6q-Jt-glI"/>
|
||||||
<constraint firstItem="p2y-0T-hQs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="1eh-91-O2N" secondAttribute="trailing" constant="20" id="GVS-6o-rmj"/>
|
<constraint firstItem="p2y-0T-hQs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="1eh-91-O2N" secondAttribute="trailing" constant="20" id="GVS-6o-rmj"/>
|
||||||
@@ -82,24 +71,24 @@
|
|||||||
</view>
|
</view>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="8b8-lM-Krq" detailTextLabel="hR1-Zb-BOk" style="IBUITableViewCellStyleValue1" id="dMt-nx-EO5">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="8b8-lM-Krq" detailTextLabel="hR1-Zb-BOk" style="IBUITableViewCellStyleValue1" id="dMt-nx-EO5">
|
||||||
<rect key="frame" x="0.0" y="236" width="600" height="44"/>
|
<rect key="frame" x="0.0" y="172" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dMt-nx-EO5" id="gdK-VV-zNb">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dMt-nx-EO5" id="gdK-VV-zNb">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq">
|
||||||
<rect key="frame" x="15" y="13" width="28.5" height="19"/>
|
<rect key="frame" x="15" y="13" width="28.5" height="19"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hR1-Zb-BOk">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hR1-Zb-BOk">
|
||||||
<rect key="frame" x="533" y="13" width="52" height="19"/>
|
<rect key="frame" x="308" y="13" width="52" height="19"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
|
||||||
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -131,23 +120,23 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="t9A-zf-Iew"/>
|
<viewControllerLayoutGuide type="bottom" id="t9A-zf-Iew"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="75P-2m-6cr">
|
<view key="view" contentMode="scaleToFill" id="75P-2m-6cr">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="WUc-3Y-Quw">
|
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="WUc-3Y-Quw">
|
||||||
<rect key="frame" x="0.0" y="324" width="600" height="276"/>
|
<rect key="frame" x="0.0" y="324" width="375" height="343"/>
|
||||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="OrganismTableViewCell" id="WVb-th-o8c" customClass="OrganismTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="OrganismTableViewCell" id="WVb-th-o8c" customClass="OrganismTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="22" width="600" height="44"/>
|
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WVb-th-o8c" id="JBq-Ml-a9p">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WVb-th-o8c" id="JBq-Ml-a9p">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OQf-Bd-Zze">
|
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OQf-Bd-Zze">
|
||||||
<rect key="frame" x="520" y="8" width="72" height="27.5"/>
|
<rect key="frame" x="295" y="8" width="72" height="27.5"/>
|
||||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||||
<inset key="contentEdgeInsets" minX="7" minY="0.0" maxX="7" maxY="0.0"/>
|
<inset key="contentEdgeInsets" minX="7" minY="0.0" maxX="7" maxY="0.0"/>
|
||||||
<state key="normal" title="mutate!"/>
|
<state key="normal" title="mutate!"/>
|
||||||
@@ -156,9 +145,9 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VZk-6K-4ut">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VZk-6K-4ut">
|
||||||
<rect key="frame" x="15" y="8" width="495" height="27.5"/>
|
<rect key="frame" x="15" y="8" width="270" height="27.5"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="17"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="17"/>
|
||||||
<color key="textColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -184,42 +173,42 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XKA-Ub-c2X">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XKA-Ub-c2X">
|
||||||
<rect key="frame" x="0.0" y="64" width="600" height="260"/>
|
<rect key="frame" x="0.0" y="64" width="375" height="260"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i7U-bW-juB" customClass="UIButton">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i7U-bW-juB" customClass="UIButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="260"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="260"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Organism" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zxy-nY-P44">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Organism" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zxy-nY-P44">
|
||||||
<rect key="frame" x="20" y="90.5" width="560" height="26.5"/>
|
<rect key="frame" x="20" y="90.5" width="335" height="26.5"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
||||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="attributes" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6Ac-xl-ldZ">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="attributes" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6Ac-xl-ldZ">
|
||||||
<rect key="frame" x="20" y="131.5" width="560" height="20.5"/>
|
<rect key="frame" x="20" y="131.5" width="335" height="20.5"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
||||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="rAZ-eJ-sxy">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="rAZ-eJ-sxy">
|
||||||
<rect key="frame" x="20" y="20" width="560" height="29"/>
|
<rect key="frame" x="20" y="20" width="335" height="29"/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="First"/>
|
<segment title="First"/>
|
||||||
<segment title="Second"/>
|
<segment title="Second"/>
|
||||||
<segment title=""/>
|
<segment title=""/>
|
||||||
</segments>
|
</segments>
|
||||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="segmentedControlValueChanged:" destination="iVv-Vc-nCL" eventType="valueChanged" id="RwG-kW-RPg"/>
|
<action selector="segmentedControlValueChanged:" destination="iVv-Vc-nCL" eventType="valueChanged" id="RwG-kW-RPg"/>
|
||||||
</connections>
|
</connections>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
<progressView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="869-wx-Odb">
|
<progressView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="869-wx-Odb">
|
||||||
<rect key="frame" x="20" y="68" width="560" height="2"/>
|
<rect key="frame" x="20" y="68" width="335" height="2"/>
|
||||||
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="trackTintColor" white="1" alpha="0.20000000000000001" colorSpace="calibratedWhite"/>
|
<color key="trackTintColor" red="1" green="1" blue="1" alpha="0.20000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</progressView>
|
</progressView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="zxy-nY-P44" firstAttribute="leading" secondItem="i7U-bW-juB" secondAttribute="leading" constant="20" id="1u1-Tq-hRn"/>
|
<constraint firstItem="zxy-nY-P44" firstAttribute="leading" secondItem="i7U-bW-juB" secondAttribute="leading" constant="20" id="1u1-Tq-hRn"/>
|
||||||
<constraint firstItem="6Ac-xl-ldZ" firstAttribute="top" secondItem="zxy-nY-P44" secondAttribute="bottom" constant="14.5" id="39B-9l-O3g"/>
|
<constraint firstItem="6Ac-xl-ldZ" firstAttribute="top" secondItem="zxy-nY-P44" secondAttribute="bottom" constant="14.5" id="39B-9l-O3g"/>
|
||||||
@@ -237,7 +226,7 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="260" id="90R-Mf-iAB"/>
|
<constraint firstAttribute="height" constant="260" id="90R-Mf-iAB"/>
|
||||||
<constraint firstItem="i7U-bW-juB" firstAttribute="leading" secondItem="XKA-Ub-c2X" secondAttribute="leading" id="e9h-f4-c37"/>
|
<constraint firstItem="i7U-bW-juB" firstAttribute="leading" secondItem="XKA-Ub-c2X" secondAttribute="leading" id="e9h-f4-c37"/>
|
||||||
@@ -246,7 +235,7 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="trailing" secondItem="XKA-Ub-c2X" secondAttribute="trailing" id="U0P-51-KT9"/>
|
<constraint firstAttribute="trailing" secondItem="XKA-Ub-c2X" secondAttribute="trailing" id="U0P-51-KT9"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="WUc-3Y-Quw" secondAttribute="trailing" id="i7I-7B-97K"/>
|
<constraint firstAttribute="trailing" secondItem="WUc-3Y-Quw" secondAttribute="trailing" id="i7I-7B-97K"/>
|
||||||
@@ -276,31 +265,31 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="t0d-B0-B7U" sceneMemberID="viewController">
|
<tableViewController id="t0d-B0-B7U" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="50" sectionHeaderHeight="10" sectionFooterHeight="10" id="uHB-Yr-ujV">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="50" sectionHeaderHeight="10" sectionFooterHeight="10" id="uHB-Yr-ujV">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<sections>
|
<sections>
|
||||||
<tableViewSection id="wIP-Hn-YfF">
|
<tableViewSection id="wIP-Hn-YfF">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Q3n-Df-v1t" detailTextLabel="Hbn-cf-Y7m" style="IBUITableViewCellStyleSubtitle" id="AXm-KE-45G">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Q3n-Df-v1t" detailTextLabel="Hbn-cf-Y7m" style="IBUITableViewCellStyleSubtitle" id="AXm-KE-45G">
|
||||||
<rect key="frame" x="0.0" y="99" width="600" height="50"/>
|
<rect key="frame" x="0.0" y="35" width="375" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AXm-KE-45G" id="9te-Wx-hkf">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AXm-KE-45G" id="9te-Wx-hkf">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accounts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q3n-Df-v1t">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accounts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q3n-Df-v1t">
|
||||||
<rect key="frame" x="15" y="6" width="82" height="24"/>
|
<rect key="frame" x="15" y="6" width="82" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Setting up multiple persistent store configurations" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Hbn-cf-Y7m">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Setting up multiple persistent store configurations" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Hbn-cf-Y7m">
|
||||||
<rect key="frame" x="15" y="30" width="263.5" height="13.5"/>
|
<rect key="frame" x="15" y="30" width="263.5" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -310,24 +299,24 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="vpt-cT-gMo" detailTextLabel="ou9-TZ-8bf" style="IBUITableViewCellStyleSubtitle" id="fsb-zw-8Ii">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="vpt-cT-gMo" detailTextLabel="ou9-TZ-8bf" style="IBUITableViewCellStyleSubtitle" id="fsb-zw-8Ii">
|
||||||
<rect key="frame" x="0.0" y="149" width="600" height="50"/>
|
<rect key="frame" x="0.0" y="85" width="375" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fsb-zw-8Ii" id="Upm-AO-Fw3">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fsb-zw-8Ii" id="Upm-AO-Fw3">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Colors" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vpt-cT-gMo">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Colors" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vpt-cT-gMo">
|
||||||
<rect key="frame" x="15" y="6" width="56" height="24"/>
|
<rect key="frame" x="15" y="6" width="56" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Observing list changes and single object changes" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ou9-TZ-8bf">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Observing list changes and single object changes" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ou9-TZ-8bf">
|
||||||
<rect key="frame" x="15" y="30" width="260.5" height="13.5"/>
|
<rect key="frame" x="15" y="30" width="260.5" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -337,24 +326,24 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="UbU-Kd-yrY" detailTextLabel="uP1-Jc-o9v" style="IBUITableViewCellStyleSubtitle" id="ekW-PJ-mbo">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="UbU-Kd-yrY" detailTextLabel="uP1-Jc-o9v" style="IBUITableViewCellStyleSubtitle" id="ekW-PJ-mbo">
|
||||||
<rect key="frame" x="0.0" y="199" width="600" height="50"/>
|
<rect key="frame" x="0.0" y="135" width="375" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekW-PJ-mbo" id="CYq-mg-PVS">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekW-PJ-mbo" id="CYq-mg-PVS">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Placemarks" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UbU-Kd-yrY">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Placemarks" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UbU-Kd-yrY">
|
||||||
<rect key="frame" x="15" y="6" width="100.5" height="24"/>
|
<rect key="frame" x="15" y="6" width="100.5" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Making changes with transactions" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uP1-Jc-o9v">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Making changes with transactions" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uP1-Jc-o9v">
|
||||||
<rect key="frame" x="15" y="30" width="179" height="13.5"/>
|
<rect key="frame" x="15" y="30" width="179" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -364,24 +353,24 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="C8Y-0y-lEG" detailTextLabel="jZw-qE-0ws" style="IBUITableViewCellStyleSubtitle" id="ph1-8z-C1m">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="C8Y-0y-lEG" detailTextLabel="jZw-qE-0ws" style="IBUITableViewCellStyleSubtitle" id="ph1-8z-C1m">
|
||||||
<rect key="frame" x="0.0" y="249" width="600" height="50"/>
|
<rect key="frame" x="0.0" y="185" width="375" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ph1-8z-C1m" id="nNz-rd-ksg">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ph1-8z-C1m" id="nNz-rd-ksg">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Time Zones" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="C8Y-0y-lEG">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Time Zones" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="C8Y-0y-lEG">
|
||||||
<rect key="frame" x="15" y="6" width="101.5" height="24"/>
|
<rect key="frame" x="15" y="6" width="101.5" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Fetching objects and raw values" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jZw-qE-0ws">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Fetching objects and raw values" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jZw-qE-0ws">
|
||||||
<rect key="frame" x="15" y="30" width="168.5" height="13.5"/>
|
<rect key="frame" x="15" y="30" width="168.5" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -391,24 +380,24 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="ZfY-Aq-Ykq" detailTextLabel="QzD-9b-k1j" style="IBUITableViewCellStyleSubtitle" id="wyK-rk-3tI">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="ZfY-Aq-Ykq" detailTextLabel="QzD-9b-k1j" style="IBUITableViewCellStyleSubtitle" id="wyK-rk-3tI">
|
||||||
<rect key="frame" x="0.0" y="299" width="600" height="50"/>
|
<rect key="frame" x="0.0" y="235" width="375" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wyK-rk-3tI" id="fLd-KK-QcW">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wyK-rk-3tI" id="fLd-KK-QcW">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZfY-Aq-Ykq">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZfY-Aq-Ykq">
|
||||||
<rect key="frame" x="15" y="6" width="61" height="24"/>
|
<rect key="frame" x="15" y="6" width="61" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Implementing a custom logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QzD-9b-k1j">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Implementing a custom logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QzD-9b-k1j">
|
||||||
<rect key="frame" x="15" y="30" width="159" height="13.5"/>
|
<rect key="frame" x="15" y="30" width="159" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -418,24 +407,24 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hSG-mG-YBw" detailTextLabel="X9P-TQ-LYh" style="IBUITableViewCellStyleSubtitle" id="xTM-Cf-0if">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hSG-mG-YBw" detailTextLabel="X9P-TQ-LYh" style="IBUITableViewCellStyleSubtitle" id="xTM-Cf-0if">
|
||||||
<rect key="frame" x="0.0" y="349" width="600" height="50"/>
|
<rect key="frame" x="0.0" y="285" width="375" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xTM-Cf-0if" id="DfO-BW-krd">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xTM-Cf-0if" id="DfO-BW-krd">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Evolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hSG-mG-YBw">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Evolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hSG-mG-YBw">
|
||||||
<rect key="frame" x="15" y="6" width="78.5" height="24"/>
|
<rect key="frame" x="15" y="6" width="78.5" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Migrating and de-migrating stores" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X9P-TQ-LYh">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Migrating and de-migrating stores" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X9P-TQ-LYh">
|
||||||
<rect key="frame" x="15" y="30" width="179.5" height="13.5"/>
|
<rect key="frame" x="15" y="30" width="179.5" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -467,69 +456,69 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="aI4-O3-OCi"/>
|
<viewControllerLayoutGuide type="bottom" id="aI4-O3-OCi"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="w8K-eN-RvU">
|
<view key="view" contentMode="scaleToFill" id="w8K-eN-RvU">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
|
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
|
||||||
<rect key="frame" x="20" y="69.5" width="552" height="36.5"/>
|
<rect key="frame" x="16" y="89.5" width="343" height="50"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfe-Yq-3Xa">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfe-Yq-3Xa">
|
||||||
<rect key="frame" x="20" y="116" width="552" height="18"/>
|
<rect key="frame" x="16" y="149.5" width="343" height="18"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hue" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sgg-Md-Nf3">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hue" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sgg-Md-Nf3">
|
||||||
<rect key="frame" x="20" y="154" width="74" height="18"/>
|
<rect key="frame" x="16" y="187.5" width="74" height="18"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Saturation" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rry-vh-bRK">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Saturation" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rry-vh-bRK">
|
||||||
<rect key="frame" x="20" y="192" width="74" height="18"/>
|
<rect key="frame" x="16" y="225.5" width="74" height="18"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Brightness" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vTa-ly-eyO">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Brightness" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vTa-ly-eyO">
|
||||||
<rect key="frame" x="20" y="230" width="74" height="18"/>
|
<rect key="frame" x="16" y="263.5" width="74" height="18"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="359" translatesAutoresizingMaskIntoConstraints="NO" id="YQ6-fq-3Wb">
|
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="359" translatesAutoresizingMaskIntoConstraints="NO" id="YQ6-fq-3Wb">
|
||||||
<rect key="frame" x="102" y="148" width="472" height="31"/>
|
<rect key="frame" x="98" y="181.5" width="263" height="31"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="hueSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="9Hy-3h-llE"/>
|
<action selector="hueSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="9Hy-3h-llE"/>
|
||||||
</connections>
|
</connections>
|
||||||
</slider>
|
</slider>
|
||||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="xXz-78-tAd">
|
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="xXz-78-tAd">
|
||||||
<rect key="frame" x="102" y="186" width="472" height="31"/>
|
<rect key="frame" x="98" y="219.5" width="263" height="31"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="saturationSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="qtU-ua-ZTc"/>
|
<action selector="saturationSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="qtU-ua-ZTc"/>
|
||||||
</connections>
|
</connections>
|
||||||
</slider>
|
</slider>
|
||||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="hpy-2d-eOP">
|
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="hpy-2d-eOP">
|
||||||
<rect key="frame" x="102" y="224" width="472" height="31"/>
|
<rect key="frame" x="98" y="257.5" width="263" height="31"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
|
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
|
||||||
</connections>
|
</connections>
|
||||||
</slider>
|
</slider>
|
||||||
<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">
|
<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="20" y="49" width="552" height="20.5"/>
|
<rect key="frame" x="16" y="69" width="343" height="20.5"/>
|
||||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="p4O-tf-dgt" firstAttribute="trailing" secondItem="w8K-eN-RvU" secondAttribute="trailingMargin" id="022-ll-1s1"/>
|
<constraint firstItem="p4O-tf-dgt" firstAttribute="trailing" secondItem="w8K-eN-RvU" secondAttribute="trailingMargin" id="022-ll-1s1"/>
|
||||||
<constraint firstItem="vTa-ly-eyO" firstAttribute="top" secondItem="rry-vh-bRK" secondAttribute="bottom" constant="20" id="1hd-Ti-CnT"/>
|
<constraint firstItem="vTa-ly-eyO" firstAttribute="top" secondItem="rry-vh-bRK" secondAttribute="bottom" constant="20" id="1hd-Ti-CnT"/>
|
||||||
@@ -591,23 +580,23 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="LNL-mj-D7l"/>
|
<viewControllerLayoutGuide type="bottom" id="LNL-mj-D7l"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="6x3-vn-Egt">
|
<view key="view" contentMode="scaleToFill" id="6x3-vn-Egt">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
|
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
|
||||||
<rect key="frame" x="4" y="64" width="592" height="268"/>
|
<rect key="frame" x="0.0" y="64" width="375" height="301.5"/>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/>
|
<segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/>
|
||||||
</connections>
|
</connections>
|
||||||
</containerView>
|
</containerView>
|
||||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp">
|
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp">
|
||||||
<rect key="frame" x="4" y="332" width="592" height="268"/>
|
<rect key="frame" x="0.0" y="365.5" width="375" height="301.5"/>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="sll-yo-mBc" kind="embed" id="AAl-HS-dq2"/>
|
<segue destination="sll-yo-mBc" kind="embed" id="AAl-HS-dq2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</containerView>
|
</containerView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="6So-f3-4Gp" firstAttribute="top" secondItem="L5f-tW-lXf" secondAttribute="bottom" id="3m8-tj-Nd4"/>
|
<constraint firstItem="6So-f3-4Gp" firstAttribute="top" secondItem="L5f-tW-lXf" secondAttribute="bottom" id="3m8-tj-Nd4"/>
|
||||||
<constraint firstAttribute="trailingMargin" secondItem="6So-f3-4Gp" secondAttribute="trailing" constant="-16" id="4L8-wZ-F59"/>
|
<constraint firstAttribute="trailingMargin" secondItem="6So-f3-4Gp" secondAttribute="trailing" constant="-16" id="4L8-wZ-F59"/>
|
||||||
@@ -636,11 +625,11 @@
|
|||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="00L-5k-Eno">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="00L-5k-Eno">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<color key="tintColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="barTintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="barTintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<textAttributes key="titleTextAttributes">
|
<textAttributes key="titleTextAttributes">
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="24"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="24"/>
|
||||||
<color key="textColor" red="0.92549019607843142" green="0.94117647058823528" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</textAttributes>
|
</textAttributes>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -657,19 +646,19 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="3AE-ED-0oj" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="3AE-ED-0oj" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="DAz-BE-6Ca">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="DAz-BE-6Ca">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="G3X-70-BCD" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="G3X-70-BCD" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
|
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="G3X-70-BCD" id="aT8-nz-i5l">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="G3X-70-BCD" id="aT8-nz-i5l">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF">
|
||||||
<rect key="frame" x="8" y="8" width="27" height="27"/>
|
<rect key="frame" x="8" y="8" width="27" height="27"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" secondItem="uQX-PI-UWF" secondAttribute="height" multiplier="1:1" id="9qA-iN-Neb"/>
|
<constraint firstAttribute="width" secondItem="uQX-PI-UWF" secondAttribute="height" multiplier="1:1" id="9qA-iN-Neb"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@@ -677,7 +666,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HJC-5w-lIN">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HJC-5w-lIN">
|
||||||
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
|
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -716,20 +705,20 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="lCE-i6-UCT" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="lCE-i6-UCT" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="Zba-8M-Zd7">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="Zba-8M-Zd7">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="zSO-3e-OVq" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="zSO-3e-OVq" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
|
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zSO-3e-OVq" id="cHA-by-n4b">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zSO-3e-OVq" id="cHA-by-n4b">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH">
|
||||||
<rect key="frame" x="8" y="8" width="27" height="27"/>
|
<rect key="frame" x="8" y="8" width="27" height="27"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" secondItem="5uq-Yi-XwH" secondAttribute="height" multiplier="1:1" id="oOe-HC-VyN"/>
|
<constraint firstAttribute="width" secondItem="5uq-Yi-XwH" secondAttribute="height" multiplier="1:1" id="oOe-HC-VyN"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@@ -737,7 +726,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Zyu-PC-WmO">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Zyu-PC-WmO">
|
||||||
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
|
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -780,11 +769,11 @@
|
|||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="6XA-6M-yvZ">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="6XA-6M-yvZ">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<color key="tintColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="barTintColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="barTintColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<textAttributes key="titleTextAttributes">
|
<textAttributes key="titleTextAttributes">
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</textAttributes>
|
</textAttributes>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -805,19 +794,19 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/>
|
<viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="k4s-iL-Krh">
|
<view key="view" contentMode="scaleToFill" id="k4s-iL-Krh">
|
||||||
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
|
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
|
<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="600" height="536"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="558"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
|
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
|
||||||
</connections>
|
</connections>
|
||||||
</mapView>
|
</mapView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<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 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 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"/>
|
<constraint firstItem="V2U-0R-Ts0" firstAttribute="leading" secondItem="k4s-iL-Krh" secondAttribute="leading" id="hk5-Rz-FyU"/>
|
||||||
@@ -831,7 +820,7 @@
|
|||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="YnG-TD-zxQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="YnG-TD-zxQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="3694" y="2020"/>
|
<point key="canvasLocation" x="3693.5" y="2019.5"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Logger-->
|
<!--Logger-->
|
||||||
<scene sceneID="n7W-0g-bbY">
|
<scene sceneID="n7W-0g-bbY">
|
||||||
@@ -842,30 +831,30 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="Cwn-Jd-4Lr"/>
|
<viewControllerLayoutGuide type="bottom" id="Cwn-Jd-4Lr"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="n9M-Je-Dj0">
|
<view key="view" contentMode="scaleToFill" id="n9M-Je-Dj0">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" alwaysBounceVertical="YES" indicatorStyle="white" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TpK-gX-CTN">
|
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" alwaysBounceVertical="YES" indicatorStyle="white" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TpK-gX-CTN">
|
||||||
<rect key="frame" x="0.0" y="142" width="600" height="458"/>
|
<rect key="frame" x="0.0" y="142" width="375" height="525"/>
|
||||||
<color key="backgroundColor" red="0.20392156862745098" green="0.28627450980392155" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="textColor" red="0.94509803921568625" green="0.7686274509803922" blue="0.058823529411764705" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.92706394195556641" green="0.72759377956390381" blue="0.064024783670902252" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<fontDescription key="fontDescription" name="AppleSDGothicNeo-Regular" family="Apple SD Gothic Neo" pointSize="15"/>
|
<fontDescription key="fontDescription" name="AppleSDGothicNeo-Regular" family="Apple SD Gothic Neo" pointSize="15"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
</textView>
|
</textView>
|
||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" momentary="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4iq-B4-k0p">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" momentary="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4iq-B4-k0p">
|
||||||
<rect key="frame" x="20" y="94" width="560" height="29"/>
|
<rect key="frame" x="20" y="94" width="335" height="29"/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="Log"/>
|
<segment title="Log"/>
|
||||||
<segment title="Error"/>
|
<segment title="Error"/>
|
||||||
<segment title="Assert"/>
|
<segment title="Assert"/>
|
||||||
</segments>
|
</segments>
|
||||||
<color key="tintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="segmentedControlValueChanged:" destination="5yy-0N-QDU" eventType="valueChanged" id="2pp-Vt-2Os"/>
|
<action selector="segmentedControlValueChanged:" destination="5yy-0N-QDU" eventType="valueChanged" id="2pp-Vt-2Os"/>
|
||||||
</connections>
|
</connections>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="4iq-B4-k0p" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" constant="20" id="6SM-eN-NxP"/>
|
<constraint firstItem="4iq-B4-k0p" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" constant="20" id="6SM-eN-NxP"/>
|
||||||
<constraint firstItem="TpK-gX-CTN" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" id="AAw-IG-taz"/>
|
<constraint firstItem="TpK-gX-CTN" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" id="AAw-IG-taz"/>
|
||||||
@@ -901,11 +890,11 @@
|
|||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wJo-mp-1pS">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wJo-mp-1pS">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<color key="tintColor" red="0.74117647058823533" green="0.76470588235294112" blue="0.7803921568627451" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="barTintColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="barTintColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<textAttributes key="titleTextAttributes">
|
<textAttributes key="titleTextAttributes">
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</textAttributes>
|
</textAttributes>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
@@ -926,30 +915,30 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="DlN-cN-JXd"/>
|
<viewControllerLayoutGuide type="bottom" id="DlN-cN-JXd"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="eC3-ql-d2o">
|
<view key="view" contentMode="scaleToFill" id="eC3-ql-d2o">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="WGY-kX-mAx">
|
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="WGY-kX-mAx">
|
||||||
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
|
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
|
||||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<view key="tableHeaderView" contentMode="scaleToFill" id="iaH-1W-Sbo">
|
<view key="tableHeaderView" contentMode="scaleToFill" id="iaH-1W-Sbo">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="80"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="80"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="YVj-dA-fyV">
|
<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>
|
<segments>
|
||||||
<segment title="Fetch"/>
|
<segment title="Fetch"/>
|
||||||
<segment title="Query"/>
|
<segment title="Query"/>
|
||||||
</segments>
|
</segments>
|
||||||
<color key="tintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="segmentedControlValueChanged:" destination="qbj-MK-nIY" eventType="valueChanged" id="Wok-dl-uq7"/>
|
<action selector="segmentedControlValueChanged:" destination="qbj-MK-nIY" eventType="valueChanged" id="Wok-dl-uq7"/>
|
||||||
</connections>
|
</connections>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="0.80000000000000004" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="YVj-dA-fyV" firstAttribute="leading" secondItem="iaH-1W-Sbo" secondAttribute="leading" constant="20" id="1dX-t7-dyR"/>
|
<constraint firstItem="YVj-dA-fyV" firstAttribute="leading" secondItem="iaH-1W-Sbo" secondAttribute="leading" constant="20" id="1dX-t7-dyR"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="YVj-dA-fyV" secondAttribute="centerY" id="HXU-Z7-jfu"/>
|
<constraint firstAttribute="centerY" secondItem="YVj-dA-fyV" secondAttribute="centerY" id="HXU-Z7-jfu"/>
|
||||||
@@ -958,17 +947,17 @@
|
|||||||
</view>
|
</view>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="6db-P0-6Ms" style="IBUITableViewCellStyleDefault" id="vUr-WV-qur">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="6db-P0-6Ms" style="IBUITableViewCellStyleDefault" id="vUr-WV-qur">
|
||||||
<rect key="frame" x="0.0" y="102" width="600" height="44"/>
|
<rect key="frame" x="0.0" y="102" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vUr-WV-qur" id="Vr0-hE-cn9">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vUr-WV-qur" id="Vr0-hE-cn9">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="567" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6db-P0-6Ms">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6db-P0-6Ms">
|
||||||
<rect key="frame" x="15" y="0.0" width="550" height="43.5"/>
|
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -981,7 +970,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="WGY-kX-mAx" firstAttribute="top" secondItem="dgu-PC-LiB" secondAttribute="bottom" id="0pS-cU-ibk"/>
|
<constraint firstItem="WGY-kX-mAx" firstAttribute="top" secondItem="dgu-PC-LiB" secondAttribute="bottom" id="0pS-cU-ibk"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="WGY-kX-mAx" secondAttribute="trailing" id="NeY-g5-CaB"/>
|
<constraint firstAttribute="trailing" secondItem="WGY-kX-mAx" secondAttribute="trailing" id="NeY-g5-CaB"/>
|
||||||
@@ -1006,30 +995,30 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="tIs-pN-OgO" customClass="FetchingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="tIs-pN-OgO" customClass="FetchingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="tVl-tT-UDk">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="tVl-tT-UDk">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="RgX-yK-1L2" detailTextLabel="QZ4-A2-x4h" style="IBUITableViewCellStyleSubtitle" id="uBt-Iy-nWP">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="RgX-yK-1L2" detailTextLabel="QZ4-A2-x4h" style="IBUITableViewCellStyleSubtitle" id="uBt-Iy-nWP">
|
||||||
<rect key="frame" x="0.0" y="100" width="600" height="60"/>
|
<rect key="frame" x="0.0" y="36" width="375" height="60"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="uBt-Iy-nWP" id="6SD-ur-9zp">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="uBt-Iy-nWP" id="6SD-ur-9zp">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RgX-yK-1L2">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RgX-yK-1L2">
|
||||||
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
|
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QZ4-A2-x4h">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QZ4-A2-x4h">
|
||||||
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
|
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -1052,30 +1041,30 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="o9D-Xm-13g" customClass="QueryingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="o9D-Xm-13g" customClass="QueryingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="bMh-zR-xwu">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="bMh-zR-xwu">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="Syt-QJ-KXg" detailTextLabel="yHS-dP-IKS" style="IBUITableViewCellStyleSubtitle" id="q7Q-aF-Ftl">
|
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="Syt-QJ-KXg" detailTextLabel="yHS-dP-IKS" style="IBUITableViewCellStyleSubtitle" id="q7Q-aF-Ftl">
|
||||||
<rect key="frame" x="0.0" y="100" width="600" height="60"/>
|
<rect key="frame" x="0.0" y="36" width="375" height="60"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q7Q-aF-Ftl" id="fc3-eg-yes">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q7Q-aF-Ftl" id="fc3-eg-yes">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Syt-QJ-KXg">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Syt-QJ-KXg">
|
||||||
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
|
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="yHS-dP-IKS">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="yHS-dP-IKS">
|
||||||
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
|
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|||||||
+6
-17
@@ -1,36 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?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">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16F73" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||||
<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>
|
|
||||||
<entity name="Place" representedClassName="CoreStoreDemo.Place" syncable="YES">
|
<entity name="Place" representedClassName="CoreStoreDemo.Place" syncable="YES">
|
||||||
<attribute name="latitude" 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" 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="subtitle" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
|
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="TimeZone" representedClassName="CoreStoreDemo.TimeZone" syncable="YES">
|
<entity name="TimeZone" representedClassName="CoreStoreDemo.TimeZone" syncable="YES">
|
||||||
<attribute name="abbreviation" optional="YES" attributeType="String" 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="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" syncable="YES"/>
|
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="name" optional="YES" attributeType="String" 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>
|
</entity>
|
||||||
<configuration name="FetchingAndQueryingDemo">
|
<configuration name="FetchingAndQueryingDemo">
|
||||||
<memberEntity name="TimeZone"/>
|
<memberEntity name="TimeZone"/>
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="ObservingDemo">
|
|
||||||
<memberEntity name="Palette"/>
|
|
||||||
</configuration>
|
|
||||||
<configuration name="TransactionsDemo">
|
<configuration name="TransactionsDemo">
|
||||||
<memberEntity name="Place"/>
|
<memberEntity name="Place"/>
|
||||||
</configuration>
|
</configuration>
|
||||||
<elements>
|
<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="Place" positionX="261" positionY="225" width="128" height="105"/>
|
||||||
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
|
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
|
||||||
</elements>
|
</elements>
|
||||||
|
|||||||
+68
-42
@@ -22,8 +22,8 @@ private struct Static {
|
|||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
_ = try? dataStack.perform(
|
||||||
_ = dataStack.beginSynchronous { (transaction) -> Void in
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
transaction.deleteAll(From<TimeZone>())
|
transaction.deleteAll(From<TimeZone>())
|
||||||
|
|
||||||
@@ -38,10 +38,8 @@ private struct Static {
|
|||||||
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
|
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
|
||||||
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
|
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
return dataStack
|
return dataStack
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -167,8 +165,8 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
fetch: { () -> [TimeZone] in
|
fetch: { () -> [TimeZone] in
|
||||||
|
|
||||||
return Static.timeZonesStack.fetchAll(
|
return Static.timeZonesStack.fetchAll(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.name)))
|
.orderBy(.ascending(\.name))
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -177,9 +175,13 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
fetch: { () -> [TimeZone] in
|
fetch: { () -> [TimeZone] in
|
||||||
|
|
||||||
return Static.timeZonesStack.fetchAll(
|
return Static.timeZonesStack.fetchAll(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Asia"),
|
.where(
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
|
format: "%K BEGINSWITH[c] %@",
|
||||||
|
#keyPath(TimeZone.name),
|
||||||
|
"Asia"
|
||||||
|
)
|
||||||
|
.orderBy(.ascending(\.secondsFromGMT))
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -188,10 +190,15 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
fetch: { () -> [TimeZone] in
|
fetch: { () -> [TimeZone] in
|
||||||
|
|
||||||
return Static.timeZonesStack.fetchAll(
|
return Static.timeZonesStack.fetchAll(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America")
|
.where(
|
||||||
|| Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Europe"),
|
format: "%K BEGINSWITH[c] %@ OR %K BEGINSWITH[c] %@",
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
|
#keyPath(TimeZone.name),
|
||||||
|
"America",
|
||||||
|
#keyPath(TimeZone.name),
|
||||||
|
"Europe"
|
||||||
|
)
|
||||||
|
.orderBy(.ascending(\.secondsFromGMT))
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -200,9 +207,13 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
fetch: { () -> [TimeZone] in
|
fetch: { () -> [TimeZone] in
|
||||||
|
|
||||||
return Static.timeZonesStack.fetchAll(
|
return Static.timeZonesStack.fetchAll(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
!Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America"),
|
.where(
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
|
format: "%K BEGINSWITH[c] %@",
|
||||||
|
#keyPath(TimeZone.name),
|
||||||
|
"America"
|
||||||
|
)
|
||||||
|
.orderBy(.ascending(\.secondsFromGMT))
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -211,23 +222,23 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
fetch: { () -> [TimeZone] in
|
fetch: { () -> [TimeZone] in
|
||||||
|
|
||||||
return Static.timeZonesStack.fetchAll(
|
return Static.timeZonesStack.fetchAll(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Where("hasDaylightSavingTime", isEqualTo: true),
|
.where(\.hasDaylightSavingTime == true)
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.name)))
|
.orderBy(.ascending(\.name))
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
private let queryingItems = [
|
private let queryingItems: [(title: String, query: () -> Any)] = [
|
||||||
(
|
(
|
||||||
title: "Number of Time Zones",
|
title: "Number of Time Zones",
|
||||||
query: { () -> Any in
|
query: { () -> Any in
|
||||||
|
|
||||||
return Static.timeZonesStack.queryValue(
|
return Static.timeZonesStack.queryValue(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Select<NSNumber>(.count(#keyPath(TimeZone.name)))
|
.select(NSNumber.self, .count(\.name))
|
||||||
)!
|
)! as Any
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@@ -235,10 +246,10 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
query: { () -> Any in
|
query: { () -> Any in
|
||||||
|
|
||||||
return Static.timeZonesStack.queryValue(
|
return Static.timeZonesStack.queryValue(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Select<String>(#keyPath(TimeZone.abbreviation)),
|
.select(String.self, .attribute(\.abbreviation))
|
||||||
Where("%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
|
.where(format: "%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
|
||||||
)!
|
)! as Any
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@@ -246,9 +257,13 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
query: { () -> Any in
|
query: { () -> Any in
|
||||||
|
|
||||||
return Static.timeZonesStack.queryAttributes(
|
return Static.timeZonesStack.queryAttributes(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Select<NSDictionary>(#keyPath(TimeZone.name), #keyPath(TimeZone.abbreviation)),
|
.select(
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.name)))
|
NSDictionary.self,
|
||||||
|
.attribute(\.name),
|
||||||
|
.attribute(\.abbreviation)
|
||||||
|
)
|
||||||
|
.orderBy(.ascending(\.name))
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -257,10 +272,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
query: { () -> Any in
|
query: { () -> Any in
|
||||||
|
|
||||||
return Static.timeZonesStack.queryAttributes(
|
return Static.timeZonesStack.queryAttributes(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Select<NSDictionary>(.count(#keyPath(TimeZone.abbreviation)), #keyPath(TimeZone.abbreviation)),
|
.select(
|
||||||
GroupBy(#keyPath(TimeZone.abbreviation)),
|
NSDictionary.self,
|
||||||
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)), .ascending(#keyPath(TimeZone.name)))
|
.count(\.abbreviation),
|
||||||
|
.attribute(\.abbreviation)
|
||||||
|
)
|
||||||
|
.groupBy(\.abbreviation)
|
||||||
|
.orderBy(
|
||||||
|
.ascending(\.secondsFromGMT),
|
||||||
|
.ascending(\.name)
|
||||||
|
)
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -269,13 +291,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
|
|||||||
query: { () -> Any in
|
query: { () -> Any in
|
||||||
|
|
||||||
return Static.timeZonesStack.queryAttributes(
|
return Static.timeZonesStack.queryAttributes(
|
||||||
From<TimeZone>(),
|
From<TimeZone>()
|
||||||
Select<NSDictionary>(
|
.select(
|
||||||
.count(#keyPath(TimeZone.hasDaylightSavingTime), as: "numberOfCountries"),
|
NSDictionary.self,
|
||||||
#keyPath(TimeZone.hasDaylightSavingTime)
|
.count(\.hasDaylightSavingTime, as: "numberOfCountries"),
|
||||||
),
|
.attribute(\.hasDaylightSavingTime)
|
||||||
GroupBy(#keyPath(TimeZone.hasDaylightSavingTime)),
|
)
|
||||||
OrderBy(.descending(#keyPath(TimeZone.hasDaylightSavingTime)))
|
.groupBy(\.hasDaylightSavingTime)
|
||||||
|
.orderBy(
|
||||||
|
.descending(\.hasDaylightSavingTime),
|
||||||
|
.ascending(\.name)
|
||||||
|
)
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,11 +17,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0.1</string>
|
<string>4.0.3</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>4</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
|
|||||||
+58
-37
@@ -10,7 +10,7 @@ import UIKit
|
|||||||
import CoreStore
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
private struct Static {
|
struct ColorsDemo {
|
||||||
|
|
||||||
enum Filter: String {
|
enum Filter: String {
|
||||||
|
|
||||||
@@ -28,13 +28,13 @@ private struct Static {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func whereClause() -> Where {
|
func whereClause() -> Where<Palette> {
|
||||||
|
|
||||||
switch self {
|
switch self {
|
||||||
|
|
||||||
case .all: return Where(true)
|
case .all: return .init()
|
||||||
case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9)
|
case .light: return (\Palette.brightness >= 0.9)
|
||||||
case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4)
|
case .dark: return (\Palette.brightness <= 0.4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,24 +43,40 @@ private struct Static {
|
|||||||
|
|
||||||
didSet {
|
didSet {
|
||||||
|
|
||||||
self.palettes.refetch(self.filter.whereClause())
|
self.palettes.refetch(
|
||||||
|
self.filter.whereClause(),
|
||||||
|
OrderBy<Palette>(.ascending(\.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> = {
|
static let palettes: ListMonitor<Palette> = {
|
||||||
|
|
||||||
try! CoreStore.addStorageAndWait(
|
try! ColorsDemo.stack.addStorageAndWait(
|
||||||
SQLiteStore(
|
SQLiteStore(
|
||||||
fileName: "ColorsDemo.sqlite",
|
fileName: "ColorsDemo.sqlite",
|
||||||
configuration: "ObservingDemo",
|
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
return ColorsDemo.stack.monitorSectionedList(
|
||||||
return CoreStore.monitorSectionedList(
|
From<Palette>()
|
||||||
From<Palette>(),
|
.sectionBy(\.colorName)
|
||||||
SectionBy(#keyPath(Palette.colorName)),
|
.orderBy(.ascending(\.hue))
|
||||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
|
||||||
)
|
)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -74,7 +90,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|
||||||
Static.palettes.removeObserver(self)
|
ColorsDemo.palettes.removeObserver(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +111,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
]
|
]
|
||||||
|
|
||||||
let filterBarButton = UIBarButtonItem(
|
let filterBarButton = UIBarButtonItem(
|
||||||
title: Static.filter.rawValue,
|
title: ColorsDemo.filter.rawValue,
|
||||||
style: .plain,
|
style: .plain,
|
||||||
target: self,
|
target: self,
|
||||||
action: #selector(self.filterBarButtonItemTouched(_:))
|
action: #selector(self.filterBarButtonItemTouched(_:))
|
||||||
@@ -110,9 +126,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
]
|
]
|
||||||
self.filterBarButton = filterBarButton
|
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?) {
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||||
@@ -134,19 +150,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
|
||||||
return Static.palettes.numberOfSections()
|
return ColorsDemo.palettes.numberOfSections()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
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 {
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
|
||||||
|
|
||||||
let palette = Static.palettes[indexPath]
|
let palette = ColorsDemo.palettes[indexPath]
|
||||||
cell.colorView?.backgroundColor = palette.color
|
cell.colorView?.backgroundColor = palette.color
|
||||||
cell.label?.text = palette.colorText
|
cell.label?.text = palette.colorText
|
||||||
|
|
||||||
@@ -162,7 +178,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
self.performSegue(
|
self.performSegue(
|
||||||
withIdentifier: "ObjectObserverDemoViewController",
|
withIdentifier: "ObjectObserverDemoViewController",
|
||||||
sender: Static.palettes[indexPath]
|
sender: ColorsDemo.palettes[indexPath]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,12 +187,14 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
switch editingStyle {
|
switch editingStyle {
|
||||||
|
|
||||||
case .delete:
|
case .delete:
|
||||||
let palette = Static.palettes[indexPath]
|
let palette = ColorsDemo.palettes[indexPath]
|
||||||
CoreStore.beginAsynchronous{ (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
transaction.delete(palette)
|
transaction.delete(palette)
|
||||||
transaction.commit { (result) -> Void in }
|
},
|
||||||
}
|
completion: { _ in }
|
||||||
|
)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@@ -185,7 +203,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||||
|
|
||||||
return Static.palettes.sectionInfoAtIndex(section).name
|
return ColorsDemo.palettes.sectionInfoAtIndex(section).name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -208,7 +226,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
|
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
|
||||||
|
|
||||||
self.filterBarButton?.title = Static.filter.rawValue
|
self.filterBarButton?.title = ColorsDemo.filter.rawValue
|
||||||
self.tableView.reloadData()
|
self.tableView.reloadData()
|
||||||
self.setTable(enabled: true)
|
self.setTable(enabled: true)
|
||||||
}
|
}
|
||||||
@@ -230,7 +248,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell {
|
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.colorView?.backgroundColor = palette.color
|
||||||
cell.label?.text = palette.colorText
|
cell.label?.text = palette.colorText
|
||||||
}
|
}
|
||||||
@@ -263,27 +281,30 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
|||||||
|
|
||||||
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
|
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
|
||||||
|
|
||||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
transaction.deleteAll(From<Palette>())
|
transaction.deleteAll(From<Palette>())
|
||||||
transaction.commit()
|
},
|
||||||
}
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
|
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
|
||||||
|
|
||||||
Static.filter = Static.filter.next()
|
ColorsDemo.filter = ColorsDemo.filter.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
|
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
|
||||||
|
|
||||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
let palette = transaction.create(Into<Palette>())
|
let palette = transaction.create(Into<Palette>())
|
||||||
palette.setInitialValues()
|
palette.setInitialValues(in: transaction)
|
||||||
|
},
|
||||||
transaction.commit()
|
completion: { _ in }
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setTable(enabled: Bool) {
|
private func setTable(enabled: Bool) {
|
||||||
|
|||||||
+41
-33
@@ -29,7 +29,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
|||||||
|
|
||||||
if let palette = newValue {
|
if let palette = newValue {
|
||||||
|
|
||||||
self.monitor = CoreStore.monitorObject(palette)
|
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@@ -50,22 +50,22 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
|||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
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>().orderBy(.ascending(\.hue))) {
|
||||||
|
|
||||||
self.monitor = CoreStore.monitorObject(palette)
|
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
_ = try? ColorsDemo.stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let palette = transaction.create(Into(Palette.self))
|
let palette = transaction.create(Into<Palette>())
|
||||||
palette.setInitialValues()
|
palette.setInitialValues(in: transaction)
|
||||||
|
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue))))!
|
let palette = ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue)))!
|
||||||
self.monitor = CoreStore.monitorObject(palette)
|
self.monitor = ColorsDemo.stack.monitorObject(palette)
|
||||||
}
|
}
|
||||||
|
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
@@ -85,7 +85,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
|||||||
|
|
||||||
// MARK: ObjectObserver
|
// MARK: ObjectObserver
|
||||||
|
|
||||||
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPath>) {
|
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPathString>) {
|
||||||
|
|
||||||
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
|
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
|
||||||
}
|
}
|
||||||
@@ -121,54 +121,62 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
|||||||
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
|
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
|
||||||
|
|
||||||
let hue = self.hueSlider?.value ?? 0
|
let hue = self.hueSlider?.value ?? 0
|
||||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { [weak self] (transaction) in
|
||||||
|
|
||||||
if let palette = transaction.edit(self?.monitor?.object) {
|
if let palette = transaction.edit(self?.monitor?.object) {
|
||||||
|
|
||||||
palette.hue = Int32(hue)
|
palette.hue .= Int(hue)
|
||||||
transaction.commit()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
|
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
|
||||||
|
|
||||||
let saturation = self.saturationSlider?.value ?? 0
|
let saturation = self.saturationSlider?.value ?? 0
|
||||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { [weak self] (transaction) in
|
||||||
|
|
||||||
if let palette = transaction.edit(self?.monitor?.object) {
|
if let palette = transaction.edit(self?.monitor?.object) {
|
||||||
|
|
||||||
palette.saturation = saturation
|
palette.saturation .= saturation
|
||||||
transaction.commit()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
|
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
|
||||||
|
|
||||||
let brightness = self.brightnessSlider?.value ?? 0
|
let brightness = self.brightnessSlider?.value ?? 0
|
||||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { [weak self] (transaction) in
|
||||||
|
|
||||||
if let palette = transaction.edit(self?.monitor?.object) {
|
if let palette = transaction.edit(self?.monitor?.object) {
|
||||||
|
|
||||||
palette.brightness = brightness
|
palette.brightness .= brightness
|
||||||
transaction.commit()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
|
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
|
||||||
|
|
||||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
ColorsDemo.stack.perform(
|
||||||
|
asynchronous: { [weak self] (transaction) in
|
||||||
|
|
||||||
transaction.delete(self?.monitor?.object)
|
transaction.delete(self?.monitor?.object)
|
||||||
transaction.commit()
|
},
|
||||||
}
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
|
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
|
||||||
|
|
||||||
self.colorNameLabel?.text = palette.colorName
|
self.colorNameLabel?.text = palette.colorName.value
|
||||||
|
|
||||||
let color = palette.color
|
let color = palette.color
|
||||||
self.colorNameLabel?.textColor = color
|
self.colorNameLabel?.textColor = color
|
||||||
@@ -176,17 +184,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
|||||||
|
|
||||||
self.hsbLabel?.text = palette.colorText
|
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,24 +14,27 @@ import CoreStore
|
|||||||
|
|
||||||
// MARK: - Palette
|
// MARK: - Palette
|
||||||
|
|
||||||
class Palette: NSManagedObject {
|
final class Palette: CoreStoreObject {
|
||||||
|
|
||||||
@NSManaged var hue: Int32
|
let hue = Value.Required<Int>("hue", initial: 0)
|
||||||
@NSManaged var saturation: Float
|
let saturation = Value.Required<Float>("saturation", initial: 0)
|
||||||
@NSManaged var brightness: Float
|
let brightness = Value.Required<Float>("brightness", initial: 0)
|
||||||
|
|
||||||
@objc dynamic var colorName: String {
|
let colorName = Value.Optional<String>(
|
||||||
|
"colorName",
|
||||||
|
isTransient: true,
|
||||||
|
customGetter: Palette.getColorName
|
||||||
|
)
|
||||||
|
|
||||||
get {
|
private static func getColorName(_ partialObject: PartialObject<Palette>) -> String? {
|
||||||
|
|
||||||
let KVCKey = #keyPath(Palette.colorName)
|
if let colorName = partialObject.primitiveValue(for: { $0.colorName }) {
|
||||||
if let colorName = self.accessValueForKVCKey(KVCKey) as? String {
|
|
||||||
|
|
||||||
return colorName
|
return colorName
|
||||||
}
|
}
|
||||||
|
|
||||||
let colorName: String
|
let colorName: String
|
||||||
switch self.hue % 360 {
|
switch partialObject.value(for: { $0.hue }) % 360 {
|
||||||
|
|
||||||
case 0 ..< 20: colorName = "Lower Reds"
|
case 0 ..< 20: colorName = "Lower Reds"
|
||||||
case 20 ..< 57: colorName = "Oranges and Browns"
|
case 20 ..< 57: colorName = "Oranges and Browns"
|
||||||
@@ -44,34 +47,32 @@ class Palette: NSManagedObject {
|
|||||||
default: colorName = "Upper Reds"
|
default: colorName = "Upper Reds"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.setPrimitiveValue(colorName, forKey: KVCKey)
|
partialObject.setPrimitiveValue(colorName, for: { $0.colorName })
|
||||||
return colorName
|
return colorName
|
||||||
}
|
}
|
||||||
set {
|
}
|
||||||
|
|
||||||
self.setValue(newValue, forKVCKey: #keyPath(Palette.colorName))
|
extension Palette {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var color: UIColor {
|
var color: UIColor {
|
||||||
|
|
||||||
return UIColor(
|
return UIColor(
|
||||||
hue: CGFloat(self.hue) / 360.0,
|
hue: CGFloat(self.hue.value) / 360.0,
|
||||||
saturation: CGFloat(self.saturation),
|
saturation: CGFloat(self.saturation.value),
|
||||||
brightness: CGFloat(self.brightness),
|
brightness: CGFloat(self.brightness.value),
|
||||||
alpha: 1.0
|
alpha: 1.0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
var colorText: String {
|
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.hue .= Int(arc4random_uniform(360))
|
||||||
self.saturation = 1.0
|
self.saturation .= Float(1.0)
|
||||||
self.brightness = Float(arc4random_uniform(70) + 30) / 100.0
|
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,10 +98,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
|||||||
switch self.segmentedControl?.selectedSegmentIndex {
|
switch self.segmentedControl?.selectedSegmentIndex {
|
||||||
|
|
||||||
case 0?:
|
case 0?:
|
||||||
self.dataStack.beginAsynchronous { (transaction) -> Void in
|
let request = NSFetchRequest<NSFetchRequestResult>()
|
||||||
|
Where<NSManagedObject>(true).applyToFetchRequest(request)
|
||||||
_ = transaction.create(Into<Palette>())
|
Where<NSManagedObject>(false).applyToFetchRequest(request)
|
||||||
}
|
|
||||||
|
|
||||||
case 1?:
|
case 1?:
|
||||||
_ = try? dataStack.addStorageAndWait(
|
_ = try? dataStack.addStorageAndWait(
|
||||||
@@ -112,10 +111,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
|||||||
)
|
)
|
||||||
|
|
||||||
case 2?:
|
case 2?:
|
||||||
self.dataStack.beginAsynchronous { (transaction) -> Void in
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
|
||||||
transaction.commit()
|
_ = self.dataStack.fetchOne(From<Place>())
|
||||||
transaction.commit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
self.present(alert, animated: true, completion: nil)
|
self.present(alert, animated: true, completion: nil)
|
||||||
|
|
||||||
|
|
||||||
let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) {
|
let modelMetadata = withExtendedLifetime(DataStack(xcodeModelName: "MigrationDemo")) {
|
||||||
(dataStack: DataStack) -> ModelMetadata in
|
(dataStack: DataStack) -> ModelMetadata in
|
||||||
|
|
||||||
let models = self.models
|
let models = self.models
|
||||||
@@ -60,7 +60,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
}
|
}
|
||||||
for model in models {
|
for model in models {
|
||||||
|
|
||||||
if model.version == storeVersion {
|
if model.schemaHistory.currentModelVersion == storeVersion {
|
||||||
|
|
||||||
return model
|
return model
|
||||||
}
|
}
|
||||||
@@ -91,6 +91,11 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
|
||||||
|
|
||||||
|
self.listMonitorDidChange(monitor)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: UITableViewDataSource
|
// MARK: UITableViewDataSource
|
||||||
|
|
||||||
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
@@ -104,7 +109,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
|
|
||||||
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
|
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
|
||||||
cell.dnaLabel?.text = "DNA: \(dna)"
|
cell.dnaLabel?.text = "DNA: \(dna)"
|
||||||
cell.mutateButtonHandler = { [weak self] _ -> Void in
|
cell.mutateButtonHandler = { [weak self] () -> Void in
|
||||||
|
|
||||||
guard let `self` = self,
|
guard let `self` = self,
|
||||||
let dataStack = self.dataStack,
|
let dataStack = self.dataStack,
|
||||||
@@ -115,16 +120,17 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
|
|
||||||
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
|
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
|
||||||
self.setEnabled(false)
|
self.setEnabled(false)
|
||||||
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in
|
dataStack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
let organism = transaction.edit(organism) as! OrganismProtocol
|
let organism = transaction.edit(organism) as! OrganismProtocol
|
||||||
organism.mutate()
|
organism.mutate()
|
||||||
|
},
|
||||||
transaction.commit { _ -> Void in
|
completion: { [weak self] _ in
|
||||||
|
|
||||||
self?.setEnabled(true)
|
self?.setEnabled(true)
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
@@ -140,29 +146,47 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private typealias ModelMetadata = (label: String, version: String, entityType: AnyClass, migrationChain: MigrationChain)
|
private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
|
||||||
|
|
||||||
private let models: [ModelMetadata] = [
|
private let models: [ModelMetadata] = [
|
||||||
(
|
(
|
||||||
label: "Model V1",
|
label: "Model V1",
|
||||||
version: "MigrationDemo",
|
|
||||||
entityType: OrganismV1.self,
|
entityType: OrganismV1.self,
|
||||||
|
schemaHistory: SchemaHistory(
|
||||||
|
XcodeDataModelSchema.from(
|
||||||
|
modelName: "MigrationDemo",
|
||||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||||
),
|
),
|
||||||
|
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||||
|
)
|
||||||
|
),
|
||||||
(
|
(
|
||||||
label: "Model V2",
|
label: "Model V2",
|
||||||
version: "MigrationDemoV2",
|
|
||||||
entityType: OrganismV2.self,
|
entityType: OrganismV2.self,
|
||||||
|
schemaHistory: SchemaHistory(
|
||||||
|
XcodeDataModelSchema.from(
|
||||||
|
modelName: "MigrationDemo",
|
||||||
migrationChain: [
|
migrationChain: [
|
||||||
"MigrationDemo": "MigrationDemoV2",
|
"MigrationDemo": "MigrationDemoV2",
|
||||||
"MigrationDemoV3": "MigrationDemoV2"
|
"MigrationDemoV3": "MigrationDemoV2"
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
migrationChain: [
|
||||||
|
"MigrationDemo": "MigrationDemoV2",
|
||||||
|
"MigrationDemoV3": "MigrationDemoV2"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
(
|
(
|
||||||
label: "Model V3",
|
label: "Model V3",
|
||||||
version: "MigrationDemoV3",
|
|
||||||
entityType: OrganismV3.self,
|
entityType: OrganismV3.self,
|
||||||
|
schemaHistory: SchemaHistory(
|
||||||
|
XcodeDataModelSchema.from(
|
||||||
|
modelName: "MigrationDemo",
|
||||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||||
|
),
|
||||||
|
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -209,21 +233,44 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
|
|
||||||
private func selectModelVersion(_ model: ModelMetadata) {
|
private func selectModelVersion(_ model: ModelMetadata) {
|
||||||
|
|
||||||
if self.dataStack?.modelVersion == model.version {
|
if self.dataStack?.modelVersion == model.schemaHistory.currentModelVersion {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
|
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
|
||||||
|
|
||||||
let dataStack = DataStack(
|
let dataStack = DataStack(schemaHistory: model.schemaHistory)
|
||||||
modelName: "MigrationDemo",
|
|
||||||
migrationChain: model.migrationChain
|
|
||||||
)
|
|
||||||
|
|
||||||
self.setEnabled(false)
|
self.setEnabled(false)
|
||||||
let progress = dataStack.addStorage(
|
let progress = dataStack.addStorage(
|
||||||
SQLiteStore(fileName: "MigrationDemo.sqlite"),
|
SQLiteStore(
|
||||||
|
fileName: "MigrationDemo.sqlite",
|
||||||
|
migrationMappingProviders: [
|
||||||
|
CustomSchemaMappingProvider(
|
||||||
|
from: "MigrationDemoV3",
|
||||||
|
to: "MigrationDemoV2",
|
||||||
|
entityMappings: [
|
||||||
|
.transformEntity(
|
||||||
|
sourceEntity: "Organism",
|
||||||
|
destinationEntity: "Organism",
|
||||||
|
transformer: { (source, createDestination) in
|
||||||
|
|
||||||
|
let destination = createDestination()
|
||||||
|
destination.enumerateAttributes { (attribute, sourceAttribute) in
|
||||||
|
|
||||||
|
if let sourceAttribute = sourceAttribute {
|
||||||
|
|
||||||
|
destination[attribute] = source[sourceAttribute]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destination["numberOfFlippers"] = source["numberOfLimbs"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
completion: { [weak self] (result) -> Void in
|
completion: { [weak self] (result) -> Void in
|
||||||
|
|
||||||
guard let `self` = self else {
|
guard let `self` = self else {
|
||||||
@@ -240,8 +287,8 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
self.set(dataStack: dataStack, model: model, scrollToSelection: true)
|
self.set(dataStack: dataStack, model: model, scrollToSelection: true)
|
||||||
|
|
||||||
let count = dataStack.queryValue(
|
let count = dataStack.queryValue(
|
||||||
From(model.entityType),
|
From<NSManagedObject>(model.entityType)
|
||||||
Select<Int>(.count(#keyPath(OrganismV1.dna))))!
|
.select(Int.self, .count(#keyPath(OrganismV1.dna))))!
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
|
|
||||||
self.setEnabled(true)
|
self.setEnabled(true)
|
||||||
@@ -250,7 +297,8 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
|
|
||||||
for i: Int64 in 0 ..< 20 {
|
for i: Int64 in 0 ..< 20 {
|
||||||
|
|
||||||
dataStack.beginAsynchronous { (transaction) -> Void in
|
dataStack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
for j: Int64 in 0 ..< 500 {
|
for j: Int64 in 0 ..< 500 {
|
||||||
|
|
||||||
@@ -258,17 +306,17 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
organism.dna = (i * 500) + j + 1
|
organism.dna = (i * 500) + j + 1
|
||||||
organism.mutate()
|
organism.mutate()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
transaction.commit()
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
dataStack.perform(
|
||||||
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in
|
asynchronous: { _ in },
|
||||||
|
completion: { [weak self] _ in
|
||||||
transaction.commit { _ in
|
|
||||||
|
|
||||||
self?.setEnabled(true)
|
self?.setEnabled(true)
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -311,10 +359,20 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
|||||||
|
|
||||||
if let dataStack = dataStack, let model = model {
|
if let dataStack = dataStack, let model = model {
|
||||||
|
|
||||||
self.segmentedControl?.selectedSegmentIndex = self.models.map { $0.version }.index(of: model.version)!
|
self.segmentedControl?.selectedSegmentIndex = self.models
|
||||||
|
.index(
|
||||||
|
where: { (arg) -> Bool in
|
||||||
|
|
||||||
|
let (_, _, schemaHistory) = arg
|
||||||
|
return schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
|
||||||
|
}
|
||||||
|
)!
|
||||||
|
|
||||||
self._dataStack = dataStack
|
self._dataStack = dataStack
|
||||||
let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna")))
|
let listMonitor = dataStack.monitorList(
|
||||||
|
From(model.entityType),
|
||||||
|
OrderBy<NSManagedObject>(.descending(#keyPath(OrganismV1.dna)))
|
||||||
|
)
|
||||||
listMonitor.addObserver(self)
|
listMonitor.addObserver(self)
|
||||||
self._listMonitor = listMonitor
|
self._listMonitor = listMonitor
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE database SYSTEM "file:///System/Library/DTDs/CoreData.dtd">
|
<!DOCTYPE database SYSTEM "file:///System/Library/DTDs/CoreData.dtd">
|
||||||
|
|
||||||
<database>
|
<database>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSPersistenceFrameworkVersion</key>
|
<key>NSPersistenceFrameworkVersion</key>
|
||||||
<integer>526</integer>
|
<integer>754</integer>
|
||||||
<key>NSStoreModelVersionHashes</key>
|
<key>NSStoreModelVersionHashes</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>XDDevAttributeMapping</key>
|
<key>XDDevAttributeMapping</key>
|
||||||
|
|||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16E195" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||||
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES">
|
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES">
|
||||||
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="hasVertebrae" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="hasVertebrae" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" elementID="numberOfFlippers" syncable="YES"/>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="Organism" positionX="-36" positionY="9" width="128" height="120"/>
|
<element name="Organism" positionX="-36" positionY="9" width="128" height="120"/>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ private struct Static {
|
|||||||
|
|
||||||
static let facebookStack: DataStack = {
|
static let facebookStack: DataStack = {
|
||||||
|
|
||||||
let dataStack = DataStack(modelName: "StackSetupDemo")
|
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
|
||||||
try! dataStack.addStorageAndWait(
|
try! dataStack.addStorageAndWait(
|
||||||
SQLiteStore(
|
SQLiteStore(
|
||||||
fileName: "AccountsDemo_FB_Male.sqlite",
|
fileName: "AccountsDemo_FB_Male.sqlite",
|
||||||
@@ -33,7 +33,8 @@ private struct Static {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
_ = dataStack.beginSynchronous { (transaction) -> Void in
|
_ = try? dataStack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
transaction.deleteAll(From<UserAccount>())
|
transaction.deleteAll(From<UserAccount>())
|
||||||
|
|
||||||
@@ -46,16 +47,15 @@ private struct Static {
|
|||||||
account2.accountType = "Facebook"
|
account2.accountType = "Facebook"
|
||||||
account2.name = "Jane Doe HCD"
|
account2.name = "Jane Doe HCD"
|
||||||
account2.friends = 314
|
account2.friends = 314
|
||||||
|
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return dataStack
|
return dataStack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static let twitterStack: DataStack = {
|
static let twitterStack: DataStack = {
|
||||||
|
|
||||||
let dataStack = DataStack(modelName: "StackSetupDemo")
|
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
|
||||||
try! dataStack.addStorageAndWait(
|
try! dataStack.addStorageAndWait(
|
||||||
SQLiteStore(
|
SQLiteStore(
|
||||||
fileName: "AccountsDemo_TW_Male.sqlite",
|
fileName: "AccountsDemo_TW_Male.sqlite",
|
||||||
@@ -71,7 +71,8 @@ private struct Static {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
_ = dataStack.beginSynchronous { (transaction) -> Void in
|
_ = try? dataStack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
transaction.deleteAll(From<UserAccount>())
|
transaction.deleteAll(From<UserAccount>())
|
||||||
|
|
||||||
@@ -84,10 +85,8 @@ private struct Static {
|
|||||||
account2.accountType = "Twitter"
|
account2.accountType = "Twitter"
|
||||||
account2.name = "#janedoe_hcd"
|
account2.name = "#janedoe_hcd"
|
||||||
account2.friends = 100
|
account2.friends = 100
|
||||||
|
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
return dataStack
|
return dataStack
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ private struct Static {
|
|||||||
var place = CoreStore.fetchOne(From<Place>())
|
var place = CoreStore.fetchOne(From<Place>())
|
||||||
if place == nil {
|
if place == nil {
|
||||||
|
|
||||||
_ = CoreStore.beginSynchronous { (transaction) -> Void in
|
_ = try? CoreStore.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let place = transaction.create(Into<Place>())
|
let place = transaction.create(Into<Place>())
|
||||||
place.setInitialValues()
|
place.setInitialValues()
|
||||||
|
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
place = CoreStore.fetchOne(From<Place>())
|
place = CoreStore.fetchOne(From<Place>())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
|
|||||||
// none
|
// none
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPath>) {
|
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPathString>) {
|
||||||
|
|
||||||
if let mapView = self.mapView {
|
if let mapView = self.mapView {
|
||||||
|
|
||||||
@@ -169,23 +169,26 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
|
|||||||
gesture.location(in: mapView),
|
gesture.location(in: mapView),
|
||||||
toCoordinateFrom: mapView
|
toCoordinateFrom: mapView
|
||||||
)
|
)
|
||||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
CoreStore.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
let place = transaction.edit(Static.placeController.object)
|
let place = transaction.edit(Static.placeController.object)
|
||||||
place?.coordinate = coordinate
|
place?.coordinate = coordinate
|
||||||
transaction.commit { (_) -> Void in }
|
},
|
||||||
}
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
|
@IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
|
||||||
|
|
||||||
_ = CoreStore.beginSynchronous { (transaction) -> Void in
|
_ = try? CoreStore.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let place = transaction.edit(Static.placeController.object)
|
let place = transaction.edit(Static.placeController.object)
|
||||||
place?.setInitialValues()
|
place?.setInitialValues()
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func geocode(place: Place) {
|
func geocode(place: Place) {
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ class BaseTestCase: XCTestCase {
|
|||||||
|
|
||||||
@nonobjc
|
@nonobjc
|
||||||
@discardableResult
|
@discardableResult
|
||||||
func prepareStack<T>(configurations: [String?] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
||||||
|
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -2,8 +2,25 @@
|
|||||||
// BaseTestDataTestCase.swift
|
// BaseTestDataTestCase.swift
|
||||||
// CoreStore
|
// CoreStore
|
||||||
//
|
//
|
||||||
// Created by John Rommel Estropia on 2016/06/11.
|
// Copyright © 2017 John Rommel Estropia
|
||||||
// Copyright © 2016 John Rommel Estropia. All rights reserved.
|
//
|
||||||
|
// 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 Foundation
|
||||||
@@ -17,7 +34,7 @@ import CoreStore
|
|||||||
class BaseTestDataTestCase: BaseTestCase {
|
class BaseTestDataTestCase: BaseTestCase {
|
||||||
|
|
||||||
@nonobjc
|
@nonobjc
|
||||||
let dateFormatter: DateFormatter = {
|
let dateFormatter: DateFormatter = cs_lazy {
|
||||||
|
|
||||||
let formatter = DateFormatter()
|
let formatter = DateFormatter()
|
||||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||||
@@ -25,12 +42,13 @@ class BaseTestDataTestCase: BaseTestCase {
|
|||||||
formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
|
formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
|
||||||
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
|
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
|
||||||
return formatter
|
return formatter
|
||||||
}()
|
}
|
||||||
|
|
||||||
@nonobjc
|
@nonobjc
|
||||||
func prepareTestDataForStack(_ stack: DataStack, configurations: [String?] = [nil]) {
|
func prepareTestDataForStack(_ stack: DataStack, configurations: [ModelConfiguration] = [nil]) {
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
try! stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
for (configurationIndex, configuration) in configurations.enumerated() {
|
for (configurationIndex, configuration) in configurations.enumerated() {
|
||||||
|
|
||||||
@@ -70,7 +88,7 @@ class BaseTestDataTestCase: BaseTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = transaction.commitAndWait()
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
- (void)test_ThatDataStacks_BridgeCorrectly {
|
- (void)test_ThatDataStacks_BridgeCorrectly {
|
||||||
|
|
||||||
CSDataStack *dataStack = [[CSDataStack alloc]
|
CSDataStack *dataStack = [[CSDataStack alloc]
|
||||||
initWithModelName:@"Model"
|
initWithXcodeModelName:@"Model"
|
||||||
bundle:[NSBundle bundleForClass:[self class]]
|
bundle:[NSBundle bundleForClass:[self class]]
|
||||||
versionChain:nil];
|
versionChain:nil];
|
||||||
XCTAssertNotNil(dataStack);
|
XCTAssertNotNil(dataStack);
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
|
|
||||||
[CSCoreStore
|
[CSCoreStore
|
||||||
setDefaultStack:[[CSDataStack alloc]
|
setDefaultStack:[[CSDataStack alloc]
|
||||||
initWithModelName:@"Model"
|
initWithXcodeModelName:@"Model"
|
||||||
bundle:[NSBundle bundleForClass:[self class]]
|
bundle:[NSBundle bundleForClass:[self class]]
|
||||||
versionChain:nil]];
|
versionChain:nil]];
|
||||||
[CSCoreStore
|
[CSCoreStore
|
||||||
@@ -212,15 +212,27 @@
|
|||||||
CSUnsafeDataTransaction *transaction = [CSCoreStore beginUnsafe];
|
CSUnsafeDataTransaction *transaction = [CSCoreStore beginUnsafe];
|
||||||
XCTAssertNotNil(transaction);
|
XCTAssertNotNil(transaction);
|
||||||
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
|
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
|
||||||
|
NSError *error;
|
||||||
|
BOOL result = [transaction commitAndWaitWithError:&error];
|
||||||
|
XCTAssertTrue(result);
|
||||||
|
XCTAssertNil(error);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
|
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
|
||||||
[CSCoreStore beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
|
NSError *error;
|
||||||
|
BOOL result = [CSCoreStore
|
||||||
|
beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
|
||||||
|
|
||||||
XCTAssertNotNil(transaction);
|
XCTAssertNotNil(transaction);
|
||||||
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
|
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
|
||||||
|
NSError *error;
|
||||||
|
XCTAssertTrue([transaction commitAndWaitWithError:&error]);
|
||||||
|
XCTAssertNil(error);
|
||||||
[expectation fulfill];
|
[expectation fulfill];
|
||||||
}];
|
}
|
||||||
|
error:&error];
|
||||||
|
XCTAssertTrue(result);
|
||||||
|
XCTAssertNil(error);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
|
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
|
||||||
@@ -228,42 +240,18 @@
|
|||||||
|
|
||||||
XCTAssertNotNil(transaction);
|
XCTAssertNotNil(transaction);
|
||||||
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
|
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
|
||||||
|
[transaction
|
||||||
|
commitWithSuccess:^{
|
||||||
|
|
||||||
[expectation fulfill];
|
[expectation fulfill];
|
||||||
|
}
|
||||||
|
failure:^(CSError *error){
|
||||||
|
|
||||||
|
XCTFail();
|
||||||
|
}];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_IOS || TARGET_OS_WATCHOS || TARGET_OS_TV
|
|
||||||
|
|
||||||
- (void)test_ThatDataStacks_CanCreateCustomFetchedResultsControllers {
|
|
||||||
|
|
||||||
[CSCoreStore
|
|
||||||
setDefaultStack:[[CSDataStack alloc]
|
|
||||||
initWithModelName:@"Model"
|
|
||||||
bundle:[NSBundle bundleForClass:[self class]]
|
|
||||||
versionChain:nil]];
|
|
||||||
[CSCoreStore
|
|
||||||
addInMemoryStorageAndWait:[CSInMemoryStore new]
|
|
||||||
error:nil];
|
|
||||||
NSFetchedResultsController *controller =
|
|
||||||
[[CSCoreStore defaultStack]
|
|
||||||
createFetchedResultsControllerFrom:CSFromClass([TestEntity1 class])
|
|
||||||
sectionBy:[CSSectionBy keyPath:CSKeyPath(TestEntity1, testString)]
|
|
||||||
fetchClauses:@[CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100),
|
|
||||||
CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil),
|
|
||||||
CSTweakRequest(^(NSFetchRequest *fetchRequest) { fetchRequest.fetchLimit = 10; })]];
|
|
||||||
|
|
||||||
XCTAssertNotNil(controller);
|
|
||||||
XCTAssertEqualObjects(controller.fetchRequest.entity.managedObjectClassName, [[TestEntity1 class] description]);
|
|
||||||
XCTAssertEqualObjects(controller.sectionNameKeyPath, CSKeyPath(TestEntity1, testString));
|
|
||||||
XCTAssertEqualObjects(controller.fetchRequest.predicate,
|
|
||||||
CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100).predicate);
|
|
||||||
XCTAssertEqualObjects(controller.fetchRequest.sortDescriptors,
|
|
||||||
CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil).sortDescriptors);
|
|
||||||
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -27,10 +27,9 @@
|
|||||||
import CoreStore
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - ConvenienceTests
|
// MARK: - ConvenienceTests
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
class ConvenienceTests: BaseTestCase {
|
class ConvenienceTests: BaseTestCase {
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -41,8 +40,8 @@ class ConvenienceTests: BaseTestCase {
|
|||||||
let controller = stack.createFetchedResultsController(
|
let controller = stack.createFetchedResultsController(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
SectionBy(#keyPath(TestEntity1.testString)),
|
SectionBy(#keyPath(TestEntity1.testString)),
|
||||||
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
|
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testString))),
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))),
|
||||||
Tweak { $0.fetchLimit = 10 }
|
Tweak { $0.fetchLimit = 10 }
|
||||||
)
|
)
|
||||||
XCTAssertEqual(controller.managedObjectContext, stack.mainContext)
|
XCTAssertEqual(controller.managedObjectContext, stack.mainContext)
|
||||||
@@ -50,11 +49,11 @@ class ConvenienceTests: BaseTestCase {
|
|||||||
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
|
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
controller.fetchRequest.sortDescriptors!,
|
controller.fetchRequest.sortDescriptors!,
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
|
||||||
)
|
)
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
controller.fetchRequest.predicate,
|
controller.fetchRequest.predicate,
|
||||||
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
|
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
|
||||||
)
|
)
|
||||||
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
|
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
|
||||||
}
|
}
|
||||||
@@ -70,8 +69,8 @@ class ConvenienceTests: BaseTestCase {
|
|||||||
let controller = transaction.createFetchedResultsController(
|
let controller = transaction.createFetchedResultsController(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
SectionBy(#keyPath(TestEntity1.testString)),
|
SectionBy(#keyPath(TestEntity1.testString)),
|
||||||
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
|
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testString))),
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))),
|
||||||
Tweak { $0.fetchLimit = 10 }
|
Tweak { $0.fetchLimit = 10 }
|
||||||
)
|
)
|
||||||
XCTAssertEqual(controller.managedObjectContext, transaction.context)
|
XCTAssertEqual(controller.managedObjectContext, transaction.context)
|
||||||
@@ -79,16 +78,14 @@ class ConvenienceTests: BaseTestCase {
|
|||||||
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
|
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
controller.fetchRequest.sortDescriptors!,
|
controller.fetchRequest.sortDescriptors!,
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
|
||||||
)
|
)
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
controller.fetchRequest.predicate,
|
controller.fetchRequest.predicate,
|
||||||
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
|
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
|
||||||
)
|
)
|
||||||
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
|
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
//
|
||||||
|
// DynamicModelTests.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 XCTest
|
||||||
|
|
||||||
|
@testable
|
||||||
|
import CoreStore
|
||||||
|
|
||||||
|
#if os(OSX)
|
||||||
|
typealias Color = NSColor
|
||||||
|
#else
|
||||||
|
|
||||||
|
typealias Color = UIColor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Animal: CoreStoreObject {
|
||||||
|
|
||||||
|
let species = Value.Required<String>("species", initial: "Swift")
|
||||||
|
let master = Relationship.ToOne<Person>("master")
|
||||||
|
let color = Transformable.Optional<Color>("color")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dog: Animal {
|
||||||
|
|
||||||
|
let nickname = Value.Optional<String>("nickname")
|
||||||
|
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",
|
||||||
|
initial: "Mr.",
|
||||||
|
customSetter: Person.setTitle
|
||||||
|
)
|
||||||
|
|
||||||
|
let name = Value.Required<String>(
|
||||||
|
"name",
|
||||||
|
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 [
|
||||||
|
String(keyPath: \Person.title),
|
||||||
|
String(keyPath: \Person.name)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - DynamicModelTests
|
||||||
|
|
||||||
|
class DynamicModelTests: BaseTestDataTestCase {
|
||||||
|
|
||||||
|
@objc
|
||||||
|
dynamic func test_ThatDynamicModels_CanBeDeclaredCorrectly() {
|
||||||
|
|
||||||
|
let dataStack = DataStack(
|
||||||
|
CoreStoreSchema(
|
||||||
|
modelVersion: "V1",
|
||||||
|
entities: [
|
||||||
|
Entity<Animal>("Animal"),
|
||||||
|
Entity<Dog>("Dog"),
|
||||||
|
Entity<Person>("Person")
|
||||||
|
],
|
||||||
|
versionLock: [
|
||||||
|
"Animal": [0x1b59d511019695cf, 0xdeb97e86c5eff179, 0x1cfd80745646cb3, 0x4ff99416175b5b9a],
|
||||||
|
"Dog": [0xe3f0afeb109b283a, 0x29998d292938eb61, 0x6aab788333cfc2a3, 0x492ff1d295910ea7],
|
||||||
|
"Person": [0x66d8bbfd8b21561f, 0xcecec69ecae3570f, 0xc4b73d71256214ef, 0x89b99bfe3e013e8b]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.prepareStack(dataStack, configurations: [nil]) { (stack) in
|
||||||
|
|
||||||
|
let k1 = String(keyPath: \Animal.species)
|
||||||
|
XCTAssertEqual(k1, "species")
|
||||||
|
|
||||||
|
let k2 = String(keyPath: \Dog.species)
|
||||||
|
XCTAssertEqual(k2, "species")
|
||||||
|
|
||||||
|
let k3 = String(keyPath: \Dog.nickname)
|
||||||
|
XCTAssertEqual(k3, "nickname")
|
||||||
|
|
||||||
|
let updateDone = self.expectation(description: "update-done")
|
||||||
|
let fetchDone = self.expectation(description: "fetch-done")
|
||||||
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
|
let animal = transaction.create(Into<Animal>())
|
||||||
|
XCTAssertEqual(animal.species.value, "Swift")
|
||||||
|
XCTAssertTrue(type(of: animal.species.value) == String.self)
|
||||||
|
|
||||||
|
animal.species .= "Sparrow"
|
||||||
|
XCTAssertEqual(animal.species.value, "Sparrow")
|
||||||
|
|
||||||
|
animal.color .= .yellow
|
||||||
|
XCTAssertEqual(animal.color.value, Color.yellow)
|
||||||
|
|
||||||
|
let dog = transaction.create(Into<Dog>())
|
||||||
|
XCTAssertEqual(dog.species.value, "Swift")
|
||||||
|
XCTAssertEqual(dog.nickname.value, nil)
|
||||||
|
XCTAssertEqual(dog.age.value, 1)
|
||||||
|
|
||||||
|
dog.species .= "Dog"
|
||||||
|
XCTAssertEqual(dog.species.value, "Dog")
|
||||||
|
|
||||||
|
dog.nickname .= "Spot"
|
||||||
|
XCTAssertEqual(dog.nickname.value, "Spot")
|
||||||
|
|
||||||
|
let person = transaction.create(Into<Person>())
|
||||||
|
XCTAssertTrue(person.pets.value.isEmpty)
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
type(of: 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, "John")
|
||||||
|
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
|
||||||
|
|
||||||
|
person.title .= "Sir"
|
||||||
|
XCTAssertEqual(person.displayName.value, "Sir John")
|
||||||
|
|
||||||
|
person.pets.value.insert(dog)
|
||||||
|
XCTAssertEqual(person.pets.count, 1)
|
||||||
|
XCTAssertEqual(person.pets.value.first, dog)
|
||||||
|
XCTAssertEqual(person.pets.value.first?.master.value, person)
|
||||||
|
XCTAssertEqual(dog.master.value, person)
|
||||||
|
XCTAssertEqual(dog.master.value?.pets.value.first, dog)
|
||||||
|
},
|
||||||
|
success: { _ in
|
||||||
|
|
||||||
|
updateDone.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
|
XCTFail()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
|
let p1 = Where<Animal>({ $0.species == "Sparrow" })
|
||||||
|
XCTAssertEqual(p1.predicate, NSPredicate(format: "%K == %@", "species", "Sparrow"))
|
||||||
|
|
||||||
|
let bird = transaction.fetchOne(From<Animal>(), p1)
|
||||||
|
XCTAssertNotNil(bird)
|
||||||
|
XCTAssertEqual(bird!.species.value, "Sparrow")
|
||||||
|
|
||||||
|
let p2 = Where<Dog>({ $0.nickname == "Spot" })
|
||||||
|
XCTAssertEqual(p2.predicate, NSPredicate(format: "%K == %@", "nickname", "Spot"))
|
||||||
|
|
||||||
|
let dog = transaction.fetchOne(From<Dog>().where(\.nickname == "Spot"))
|
||||||
|
XCTAssertNotNil(dog)
|
||||||
|
XCTAssertEqual(dog!.nickname.value, "Spot")
|
||||||
|
XCTAssertEqual(dog!.species.value, "Dog")
|
||||||
|
|
||||||
|
let person = transaction.fetchOne(From<Person>())
|
||||||
|
XCTAssertNotNil(person)
|
||||||
|
XCTAssertEqual(person!.pets.value.first, dog)
|
||||||
|
|
||||||
|
let p3 = Where<Dog>({ $0.age == 10 })
|
||||||
|
XCTAssertEqual(p3.predicate, NSPredicate(format: "%K == %d", "age", 10))
|
||||||
|
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>()
|
||||||
|
.where(\Animal.species == "Dog" && \.age == 10)
|
||||||
|
)
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>()
|
||||||
|
.where(\.age == 10 && \Animal.species == "Dog")
|
||||||
|
.orderBy(.ascending({ $0.species }))
|
||||||
|
)
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>(),
|
||||||
|
Where<Dog>({ $0.age > 10 && $0.age <= 15 })
|
||||||
|
)
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>(),
|
||||||
|
Where<Dog>({ $0.species == "Dog" && $0.age == 10 })
|
||||||
|
)
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>(),
|
||||||
|
Where<Dog>({ $0.age == 10 && $0.species == "Dog" })
|
||||||
|
)
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>(),
|
||||||
|
Where<Dog>({ $0.age > 10 && $0.age <= 15 })
|
||||||
|
)
|
||||||
|
_ = transaction.fetchAll(
|
||||||
|
From<Dog>(),
|
||||||
|
(\Dog.age > 10 && \Dog.age <= 15)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
success: { _ in
|
||||||
|
|
||||||
|
fetchDone.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
|
XCTFail()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.waitAndCheckExpectations()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
dynamic func test_ThatDynamicModelKeyPaths_CanBeCreated() {
|
||||||
|
|
||||||
|
XCTAssertEqual(String(keyPath: \Animal.species), "species")
|
||||||
|
XCTAssertEqual(String(keyPath: \Dog.species), "species")
|
||||||
|
}
|
||||||
|
|
||||||
|
@nonobjc
|
||||||
|
func prepareStack(_ dataStack: DataStack, configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> Void) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
try configurations.forEach { (configuration) in
|
||||||
|
|
||||||
|
try dataStack.addStorageAndWait(
|
||||||
|
SQLiteStore(
|
||||||
|
fileURL: SQLiteStore.defaultRootDirectory
|
||||||
|
.appendingPathComponent(UUID().uuidString)
|
||||||
|
.appendingPathComponent("\(type(of: self))_\((configuration ?? "-null-")).sqlite"),
|
||||||
|
configuration: configuration,
|
||||||
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch let error as NSError {
|
||||||
|
|
||||||
|
XCTFail(error.coreStoreDumpString)
|
||||||
|
}
|
||||||
|
closure(dataStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,16 +85,21 @@ final class ErrorTests: XCTestCase {
|
|||||||
|
|
||||||
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
|
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
|
||||||
|
|
||||||
let model = NSManagedObjectModel.fromBundle(Bundle(for: type(of: self)), modelName: "Model")
|
let schemaHistory = SchemaHistory(
|
||||||
|
XcodeDataModelSchema.from(
|
||||||
|
modelName: "Model",
|
||||||
|
bundle: Bundle(for: type(of: self))
|
||||||
|
)
|
||||||
|
)
|
||||||
let version = "1.0.0"
|
let version = "1.0.0"
|
||||||
|
|
||||||
let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version)
|
let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: schemaHistory.rawModel, targetModelVersion: version)
|
||||||
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
|
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
|
||||||
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
|
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
|
||||||
|
|
||||||
let userInfo: NSDictionary = [
|
let userInfo: NSDictionary = [
|
||||||
"localStoreURL": dummyURL,
|
"localStoreURL": dummyURL,
|
||||||
"targetModel": model,
|
"targetModel": schemaHistory.rawModel,
|
||||||
"targetModelVersion": version
|
"targetModelVersion": version
|
||||||
]
|
]
|
||||||
let objcError = error.bridgeToObjectiveC
|
let objcError = error.bridgeToObjectiveC
|
||||||
|
|||||||
+633
-443
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@ final class FromTests: BaseTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let from = From()
|
let from = From<NSManagedObject>()
|
||||||
XCTAssert(from.entityClass === NSManagedObject.self)
|
XCTAssert(from.entityClass === NSManagedObject.self)
|
||||||
XCTAssertNil(from.configurations)
|
XCTAssertNil(from.configurations)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ final class GroupByTests: BaseTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let groupBy = GroupBy()
|
let groupBy = GroupBy<NSManagedObject>()
|
||||||
XCTAssertEqual(groupBy, GroupBy([] as [String]))
|
XCTAssertEqual(groupBy, GroupBy([] as [String]))
|
||||||
XCTAssertNotEqual(groupBy, GroupBy("key"))
|
XCTAssertNotEqual(groupBy, GroupBy("key"))
|
||||||
XCTAssertTrue(groupBy.keyPaths.isEmpty)
|
XCTAssertTrue(groupBy.keyPaths.isEmpty)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let groupBy = GroupBy("key1")
|
let groupBy = GroupBy<NSManagedObject>("key1")
|
||||||
XCTAssertEqual(groupBy, GroupBy("key1"))
|
XCTAssertEqual(groupBy, GroupBy("key1"))
|
||||||
XCTAssertEqual(groupBy, GroupBy(["key1"]))
|
XCTAssertEqual(groupBy, GroupBy(["key1"]))
|
||||||
XCTAssertNotEqual(groupBy, GroupBy("key2"))
|
XCTAssertNotEqual(groupBy, GroupBy("key2"))
|
||||||
@@ -53,7 +53,7 @@ final class GroupByTests: BaseTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let groupBy = GroupBy("key1", "key2")
|
let groupBy = GroupBy<NSManagedObject>("key1", "key2")
|
||||||
XCTAssertEqual(groupBy, GroupBy("key1", "key2"))
|
XCTAssertEqual(groupBy, GroupBy("key1", "key2"))
|
||||||
XCTAssertEqual(groupBy, GroupBy(["key1", "key2"]))
|
XCTAssertEqual(groupBy, GroupBy(["key1", "key2"]))
|
||||||
XCTAssertNotEqual(groupBy, GroupBy("key2", "key1"))
|
XCTAssertNotEqual(groupBy, GroupBy("key2", "key1"))
|
||||||
@@ -66,7 +66,7 @@ final class GroupByTests: BaseTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (dataStack) in
|
self.prepareStack { (dataStack) in
|
||||||
|
|
||||||
let groupBy = GroupBy(#keyPath(TestEntity1.testString))
|
let groupBy = GroupBy<NSManagedObject>(#keyPath(TestEntity1.testString))
|
||||||
|
|
||||||
let request = CoreStoreFetchRequest()
|
let request = CoreStoreFetchRequest()
|
||||||
_ = From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext)
|
_ = From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext)
|
||||||
|
|||||||
+144
-148
@@ -36,40 +36,40 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatAttributeProtocols_BehaveCorrectly() {
|
dynamic func test_ThatAttributeProtocols_BehaveCorrectly() {
|
||||||
|
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSNumber(value: true))?.boolValue, true)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: true))?.boolValue, true)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT))
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT))
|
||||||
|
|
||||||
XCTAssertEqual(NSDecimalNumber.cs_fromNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
||||||
XCTAssertEqual(NSDecimalNumber.cs_fromNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
||||||
XCTAssertEqual(NSDecimalNumber.cs_fromNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
||||||
XCTAssertEqual(NSDecimalNumber.cs_fromNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
||||||
XCTAssertEqual(NSDecimalNumber.cs_fromNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
||||||
XCTAssertEqual(NSDecimalNumber.cs_fromNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
||||||
|
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
|
||||||
XCTAssertEqual(NSNumber.cs_fromNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
|
||||||
|
|
||||||
XCTAssertNil(NSDecimalNumber.cs_fromNativeType(NSNumber(value: true)))
|
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: true)))
|
||||||
XCTAssertNil(NSDecimalNumber.cs_fromNativeType(NSNumber(value: Int16.max)))
|
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max)))
|
||||||
XCTAssertNil(NSDecimalNumber.cs_fromNativeType(NSNumber(value: Int32.max)))
|
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max)))
|
||||||
XCTAssertNil(NSDecimalNumber.cs_fromNativeType(NSNumber(value: Int64.max)))
|
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max)))
|
||||||
XCTAssertNil(NSDecimalNumber.cs_fromNativeType(NSNumber(value: MAXFLOAT)))
|
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT)))
|
||||||
XCTAssertNil(NSDecimalNumber.cs_fromNativeType(NSNumber(value: Double(MAXFLOAT))))
|
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT))))
|
||||||
|
|
||||||
XCTAssertEqual(true.cs_toNativeType(), NSNumber(value: true))
|
XCTAssertEqual(true.cs_toQueryableNativeType(), NSNumber(value: true))
|
||||||
XCTAssertEqual(Int16.max.cs_toNativeType(), NSNumber(value: Int16.max))
|
XCTAssertEqual(Int16.max.cs_toQueryableNativeType(), NSNumber(value: Int16.max))
|
||||||
XCTAssertEqual(Int32.max.cs_toNativeType(), NSNumber(value: Int32.max))
|
XCTAssertEqual(Int32.max.cs_toQueryableNativeType(), NSNumber(value: Int32.max))
|
||||||
XCTAssertEqual(Int64.max.cs_toNativeType(), NSNumber(value: Int64.max))
|
XCTAssertEqual(Int64.max.cs_toQueryableNativeType(), NSNumber(value: Int64.max))
|
||||||
XCTAssertEqual(MAXFLOAT.cs_toNativeType(), NSNumber(value: MAXFLOAT))
|
XCTAssertEqual(MAXFLOAT.cs_toQueryableNativeType(), NSNumber(value: MAXFLOAT))
|
||||||
XCTAssertEqual(Double(MAXFLOAT).cs_toNativeType(), NSNumber(value: Double(MAXFLOAT)))
|
XCTAssertEqual(Double(MAXFLOAT).cs_toQueryableNativeType(), NSNumber(value: Double(MAXFLOAT)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -77,10 +77,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let object = try transaction.importObject(
|
let object = try transaction.importObject(
|
||||||
Into<TestEntity1>(),
|
Into<TestEntity1>(),
|
||||||
source: [
|
source: [
|
||||||
@@ -96,11 +97,13 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object)
|
XCTAssertNil(object)
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 0)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 0)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
XCTAssertEqual(stack.fetchCount(From<TestEntity1>()), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,12 +112,15 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let _ = try transaction.importObject(
|
let errorExpectation = self.expectation(description: "error")
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
_ = try transaction.importObject(
|
||||||
Into<TestEntity1>(),
|
Into<TestEntity1>(),
|
||||||
source: [
|
source: [
|
||||||
#keyPath(TestEntity1.testBoolean): NSNumber(value: true),
|
#keyPath(TestEntity1.testBoolean): NSNumber(value: true),
|
||||||
@@ -143,13 +149,14 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object?.testData)
|
XCTAssertNil(object?.testData)
|
||||||
XCTAssertNil(object?.testDate)
|
XCTAssertNil(object?.testDate)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.checkExpectationsImmediately()
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
self.checkExpectationsImmediately()
|
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,10 +165,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let object = try transaction.importObject(
|
let object = try transaction.importObject(
|
||||||
Into<TestEntity1>(),
|
Into<TestEntity1>(),
|
||||||
source: [
|
source: [
|
||||||
@@ -203,12 +211,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
XCTAssertEqual(object?.testData, ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-02T00:00:00Z")!)
|
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-02T00:00:00Z")!)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,10 +225,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
[
|
[
|
||||||
#keyPath(TestEntity1.testBoolean): NSNumber(value: true),
|
#keyPath(TestEntity1.testBoolean): NSNumber(value: true),
|
||||||
@@ -257,12 +266,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
||||||
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,9 +280,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
do {
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
let errorExpectation = self.expectation(description: "error")
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
@@ -316,13 +328,14 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object?.testData)
|
XCTAssertNil(object?.testData)
|
||||||
XCTAssertNil(object?.testDate)
|
XCTAssertNil(object?.testDate)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.checkExpectationsImmediately()
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
self.checkExpectationsImmediately()
|
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,10 +344,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
[
|
[
|
||||||
#keyPath(TestEntity1.testBoolean): NSNumber(value: true),
|
#keyPath(TestEntity1.testBoolean): NSNumber(value: true),
|
||||||
@@ -374,12 +388,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,8 +403,10 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
do {
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
@@ -410,10 +426,6 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object)
|
XCTAssertNil(object)
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
||||||
}
|
}
|
||||||
catch {
|
|
||||||
|
|
||||||
XCTFail()
|
|
||||||
}
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let object = try transaction.importUniqueObject(
|
let object = try transaction.importUniqueObject(
|
||||||
@@ -432,7 +444,7 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object)
|
XCTAssertNil(object)
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
||||||
|
|
||||||
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
||||||
XCTAssertNotNil(existingObjects)
|
XCTAssertNotNil(existingObjects)
|
||||||
XCTAssertEqual(existingObjects?.count, 1)
|
XCTAssertEqual(existingObjects?.count, 1)
|
||||||
|
|
||||||
@@ -445,13 +457,15 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||||
XCTAssertEqual(existingObject?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
|
XCTAssertEqual(existingObject?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatImportUniqueObjects_ImportsLastOfImportSourcesWithSameIDs() {
|
dynamic func test_ThatImportUniqueObjects_ImportsLastOfImportSourcesWithSameIDs() {
|
||||||
@@ -459,11 +473,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
[
|
[
|
||||||
#keyPath(TestEntity1.testEntityID): NSNumber(value: 106),
|
#keyPath(TestEntity1.testEntityID): NSNumber(value: 106),
|
||||||
@@ -502,12 +516,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
||||||
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,11 +531,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
[
|
[
|
||||||
#keyPath(TestEntity1.testEntityID): NSNumber(value: 106),
|
#keyPath(TestEntity1.testEntityID): NSNumber(value: 106),
|
||||||
@@ -551,7 +565,9 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(objects.count, 2)
|
XCTAssertEqual(objects.count, 2)
|
||||||
|
|
||||||
zip(objects, sourceArray)
|
zip(objects, sourceArray)
|
||||||
.forEach { object, dictionary in
|
.forEach {
|
||||||
|
|
||||||
|
let (object, dictionary) = $0
|
||||||
XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber)
|
XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber)
|
||||||
XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber)
|
XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber)
|
||||||
XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber)
|
XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber)
|
||||||
@@ -561,12 +577,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,11 +592,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
let errorExpectation = self.expectation(description: "error")
|
||||||
do {
|
do {
|
||||||
|
|
||||||
@@ -604,7 +620,7 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
errorExpectation.fulfill()
|
errorExpectation.fulfill()
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 6)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 6)
|
||||||
|
|
||||||
let object = transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
|
let object = transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
|
||||||
XCTAssertNotNil(object)
|
XCTAssertNotNil(object)
|
||||||
XCTAssertEqual(object?.testEntityID, NSNumber(value: 106))
|
XCTAssertEqual(object?.testEntityID, NSNumber(value: 106))
|
||||||
XCTAssertNil(object?.testBoolean)
|
XCTAssertNil(object?.testBoolean)
|
||||||
@@ -614,13 +630,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object?.testData)
|
XCTAssertNil(object?.testData)
|
||||||
XCTAssertNil(object?.testDate)
|
XCTAssertNil(object?.testDate)
|
||||||
}
|
}
|
||||||
catch {
|
|
||||||
|
|
||||||
XCTFail()
|
|
||||||
}
|
|
||||||
self.checkExpectationsImmediately()
|
self.checkExpectationsImmediately()
|
||||||
}
|
}
|
||||||
do {
|
)
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
let errorExpectation = self.expectation(description: "error")
|
||||||
do {
|
do {
|
||||||
@@ -645,7 +659,7 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
errorExpectation.fulfill()
|
errorExpectation.fulfill()
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 6)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 6)
|
||||||
|
|
||||||
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
||||||
XCTAssertNotNil(existingObjects)
|
XCTAssertNotNil(existingObjects)
|
||||||
XCTAssertEqual(existingObjects?.count, 1)
|
XCTAssertEqual(existingObjects?.count, 1)
|
||||||
|
|
||||||
@@ -659,14 +673,14 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||||
XCTAssertEqual(existingObject?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
|
XCTAssertEqual(existingObject?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
|
||||||
}
|
}
|
||||||
|
self.checkExpectationsImmediately()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
self.checkExpectationsImmediately()
|
|
||||||
}
|
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,8 +690,10 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
do {
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
@@ -704,10 +720,6 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
XCTAssertEqual(object?.testData, ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!)
|
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!)
|
||||||
}
|
}
|
||||||
catch {
|
|
||||||
|
|
||||||
XCTFail()
|
|
||||||
}
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let object = try transaction.importUniqueObject(
|
let object = try transaction.importUniqueObject(
|
||||||
@@ -733,19 +745,20 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
XCTAssertEqual(object?.testData, ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-07T00:00:00Z")!)
|
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-07T00:00:00Z")!)
|
||||||
|
|
||||||
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
|
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
|
||||||
XCTAssertNotNil(existingObjects)
|
XCTAssertNotNil(existingObjects)
|
||||||
XCTAssertEqual(existingObjects?.count, 1)
|
XCTAssertEqual(existingObjects?.count, 1)
|
||||||
|
|
||||||
let existingObject = existingObjects?[0]
|
let existingObject = existingObjects?[0]
|
||||||
XCTAssertEqual(existingObject, object)
|
XCTAssertEqual(existingObject, object)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,11 +768,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
[
|
[
|
||||||
#keyPath(TestEntity1.testEntityID): NSNumber(value: 106),
|
#keyPath(TestEntity1.testEntityID): NSNumber(value: 106),
|
||||||
@@ -798,12 +811,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
||||||
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,8 +826,10 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
do {
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
let errorExpectation = self.expectation(description: "error")
|
||||||
do {
|
do {
|
||||||
@@ -851,17 +866,15 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
errorExpectation.fulfill()
|
errorExpectation.fulfill()
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
||||||
|
|
||||||
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)))
|
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)))
|
||||||
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 107)))
|
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 107)))
|
||||||
}
|
|
||||||
catch {
|
|
||||||
|
|
||||||
XCTFail()
|
|
||||||
}
|
}
|
||||||
|
transaction.unsafeContext().reset()
|
||||||
self.checkExpectationsImmediately()
|
self.checkExpectationsImmediately()
|
||||||
transaction.context.reset()
|
|
||||||
}
|
}
|
||||||
stack.beginSynchronous { (transaction) in
|
)
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
let errorExpectation = self.expectation(description: "error")
|
||||||
do {
|
do {
|
||||||
@@ -897,7 +910,7 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
errorExpectation.fulfill()
|
errorExpectation.fulfill()
|
||||||
|
|
||||||
let object = transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
|
let object = transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
|
||||||
XCTAssertNotNil(object)
|
XCTAssertNotNil(object)
|
||||||
XCTAssertEqual(object?.testEntityID, NSNumber(value: 106))
|
XCTAssertEqual(object?.testEntityID, NSNumber(value: 106))
|
||||||
XCTAssertNil(object?.testBoolean)
|
XCTAssertNil(object?.testBoolean)
|
||||||
@@ -907,14 +920,12 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertNil(object?.testData)
|
XCTAssertNil(object?.testData)
|
||||||
XCTAssertNil(object?.testDate)
|
XCTAssertNil(object?.testDate)
|
||||||
}
|
}
|
||||||
catch {
|
|
||||||
|
|
||||||
XCTFail()
|
|
||||||
}
|
|
||||||
self.checkExpectationsImmediately()
|
|
||||||
transaction.context.reset()
|
transaction.context.reset()
|
||||||
|
self.checkExpectationsImmediately()
|
||||||
}
|
}
|
||||||
stack.beginSynchronous { (transaction) in
|
)
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let errorExpectation = self.expectation(description: "error")
|
let errorExpectation = self.expectation(description: "error")
|
||||||
do {
|
do {
|
||||||
@@ -942,7 +953,7 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
errorExpectation.fulfill()
|
errorExpectation.fulfill()
|
||||||
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
|
||||||
|
|
||||||
let object = transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
let object = transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
||||||
XCTAssertNotNil(object)
|
XCTAssertNotNil(object)
|
||||||
XCTAssertEqual(object?.testEntityID, NSNumber(value: 105))
|
XCTAssertEqual(object?.testEntityID, NSNumber(value: 105))
|
||||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||||
@@ -952,20 +963,22 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
XCTAssertEqual(object?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
|
||||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
|
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
|
||||||
|
|
||||||
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
||||||
XCTAssertNotNil(existingObjects)
|
XCTAssertNotNil(existingObjects)
|
||||||
XCTAssertEqual(existingObjects?.count, 1)
|
XCTAssertEqual(existingObjects?.count, 1)
|
||||||
|
|
||||||
let existingObject = existingObjects?[0]
|
let existingObject = existingObjects?[0]
|
||||||
XCTAssertEqual(existingObject, object)
|
XCTAssertEqual(existingObject, object)
|
||||||
}
|
}
|
||||||
|
transaction.context.reset()
|
||||||
|
self.checkExpectationsImmediately()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
self.checkExpectationsImmediately()
|
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,11 +988,11 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
self.prepareStack { (stack) in
|
self.prepareStack { (stack) in
|
||||||
|
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
|
|
||||||
stack.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
try stack.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
let sourceArray: [TestEntity1.ImportSource] = [
|
let sourceArray: [TestEntity1.ImportSource] = [
|
||||||
[
|
[
|
||||||
#keyPath(TestEntity1.testEntityID): NSNumber(value: 105),
|
#keyPath(TestEntity1.testEntityID): NSNumber(value: 105),
|
||||||
@@ -1019,19 +1032,19 @@ class ImportTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
|
||||||
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
|
||||||
}
|
}
|
||||||
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
|
||||||
XCTAssertNotNil(existingObjects)
|
XCTAssertNotNil(existingObjects)
|
||||||
XCTAssertEqual(existingObjects?.count, 1)
|
XCTAssertEqual(existingObjects?.count, 1)
|
||||||
|
|
||||||
let existingObject = existingObjects?[0]
|
let existingObject = existingObjects?[0]
|
||||||
XCTAssertEqual(existingObject, objects[0])
|
XCTAssertEqual(existingObject, objects[0])
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.context.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1083,42 +1096,25 @@ extension TestEntity1: ImportableUniqueObject {
|
|||||||
|
|
||||||
// MARK: ImportableUniqueObject
|
// MARK: ImportableUniqueObject
|
||||||
|
|
||||||
typealias UniqueIDType = NSNumber
|
typealias UniqueIDType = Int64
|
||||||
|
|
||||||
static var uniqueIDKeyPath: String {
|
static var uniqueIDKeyPath: String {
|
||||||
|
|
||||||
return #keyPath(TestEntity1.testEntityID)
|
return #keyPath(TestEntity1.testEntityID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uniqueIDValue: NSNumber {
|
|
||||||
|
|
||||||
get {
|
|
||||||
|
|
||||||
guard let ID = self.testEntityID else {
|
|
||||||
|
|
||||||
XCTFail()
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return ID
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
|
|
||||||
self.testEntityID = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
|
static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
|
||||||
|
|
||||||
return source["skip_update"] == nil
|
return source["skip_update"] == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> NSNumber? {
|
static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> Int64? {
|
||||||
|
|
||||||
if let _ = source["throw_on_id"] {
|
if let _ = source["throw_on_id"] {
|
||||||
|
|
||||||
throw TestIDError()
|
throw TestIDError()
|
||||||
}
|
}
|
||||||
return source[(#keyPath(TestEntity1.testEntityID))] as? NSNumber
|
return source[(#keyPath(TestEntity1.testEntityID))] as? Int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(from source: ImportSource, in transaction: BaseDataTransaction) throws {
|
func update(from source: ImportSource, in transaction: BaseDataTransaction) throws {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ final class IntoTests: XCTestCase {
|
|||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatIntoClauseConstants_AreCorrect() {
|
dynamic func test_ThatIntoClauseConstants_AreCorrect() {
|
||||||
|
|
||||||
XCTAssertEqual(Into<NSManagedObject>.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
|
XCTAssertEqual(DataStack.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -44,7 +44,7 @@ final class IntoTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into()
|
let into = Into<NSManagedObject>()
|
||||||
XCTAssert(into.entityClass === NSManagedObject.self)
|
XCTAssert(into.entityClass === NSManagedObject.self)
|
||||||
XCTAssertNil(into.configuration)
|
XCTAssertNil(into.configuration)
|
||||||
XCTAssertTrue(into.inferStoreIfPossible)
|
XCTAssertTrue(into.inferStoreIfPossible)
|
||||||
@@ -58,14 +58,7 @@ final class IntoTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into<TestEntity1>()
|
let into = Into(TestEntity1.self)
|
||||||
XCTAssert(into.entityClass === TestEntity1.self)
|
|
||||||
XCTAssertNil(into.configuration)
|
|
||||||
XCTAssertTrue(into.inferStoreIfPossible)
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass)
|
|
||||||
XCTAssert(into.entityClass === TestEntity1.self)
|
XCTAssert(into.entityClass === TestEntity1.self)
|
||||||
XCTAssertNil(into.configuration)
|
XCTAssertNil(into.configuration)
|
||||||
XCTAssertTrue(into.inferStoreIfPossible)
|
XCTAssertTrue(into.inferStoreIfPossible)
|
||||||
@@ -84,13 +77,6 @@ final class IntoTests: XCTestCase {
|
|||||||
XCTAssertEqual(into.configuration, "Config1")
|
XCTAssertEqual(into.configuration, "Config1")
|
||||||
XCTAssertFalse(into.inferStoreIfPossible)
|
XCTAssertFalse(into.inferStoreIfPossible)
|
||||||
}
|
}
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
|
||||||
XCTAssert(into.entityClass === TestEntity1.self)
|
|
||||||
XCTAssertEqual(into.configuration, "Config1")
|
|
||||||
XCTAssertFalse(into.inferStoreIfPossible)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -98,43 +84,30 @@ final class IntoTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into()
|
let into = Into<NSManagedObject>()
|
||||||
XCTAssertEqual(into, Into())
|
|
||||||
XCTAssertEqual(into, Into<NSManagedObject>())
|
XCTAssertEqual(into, Into<NSManagedObject>())
|
||||||
XCTAssertEqual(into, Into(NSManagedObject.self as AnyClass))
|
XCTAssertEqual(into, Into(NSManagedObject.self))
|
||||||
XCTAssertFalse(into == Into<TestEntity1>())
|
XCTAssertNotEqual(into, Into<NSManagedObject>(TestEntity1.self))
|
||||||
XCTAssertNotEqual(into, Into<NSManagedObject>("Config1"))
|
XCTAssertNotEqual(into, Into<NSManagedObject>("Config1"))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into<TestEntity1>()
|
let into = Into<TestEntity1>()
|
||||||
XCTAssertEqual(into, Into<TestEntity1>())
|
XCTAssertEqual(into, Into<TestEntity1>())
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
|
XCTAssertEqual(into, Into(TestEntity1.self))
|
||||||
XCTAssertFalse(into == Into<TestEntity2>())
|
|
||||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into<TestEntity1>()
|
let into = Into(TestEntity1.self)
|
||||||
XCTAssertEqual(into, Into<TestEntity1>())
|
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
|
|
||||||
XCTAssertFalse(into == Into<TestEntity2>())
|
|
||||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass)
|
|
||||||
XCTAssert(into == Into<TestEntity1>())
|
XCTAssert(into == Into<TestEntity1>())
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self))
|
XCTAssertEqual(into, Into(TestEntity1.self))
|
||||||
XCTAssertFalse(into == Into<TestEntity2>())
|
|
||||||
XCTAssertFalse(into == Into<TestEntity1>("Config1"))
|
XCTAssertFalse(into == Into<TestEntity1>("Config1"))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into<TestEntity1>("Config1")
|
let into = Into<TestEntity1>("Config1")
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass, "Config1"))
|
|
||||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
|
||||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
@@ -142,16 +115,14 @@ final class IntoTests: XCTestCase {
|
|||||||
let into = Into(TestEntity1.self, "Config1")
|
let into = Into(TestEntity1.self, "Config1")
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||||
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
||||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
|
||||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
let into = Into(TestEntity1.self, "Config1")
|
||||||
XCTAssert(into == Into<TestEntity1>("Config1"))
|
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
||||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||||
XCTAssertFalse(into == Into<TestEntity1>("Config2"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,45 +131,9 @@ final class IntoTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let into = Into()
|
let into = Into<NSManagedObject>()
|
||||||
let objcInto = into.bridgeToObjectiveC
|
let objcInto = into.bridgeToObjectiveC
|
||||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||||
}
|
}
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into<TestEntity1>()
|
|
||||||
let objcInto = into.bridgeToObjectiveC
|
|
||||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass)
|
|
||||||
let objcInto = into.bridgeToObjectiveC
|
|
||||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass)
|
|
||||||
let objcInto = into.bridgeToObjectiveC
|
|
||||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into<TestEntity1>("Config1")
|
|
||||||
let objcInto = into.bridgeToObjectiveC
|
|
||||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self, "Config1")
|
|
||||||
let objcInto = into.bridgeToObjectiveC
|
|
||||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
|
|
||||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
|
||||||
let objcInto = into.bridgeToObjectiveC
|
|
||||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ import XCTest
|
|||||||
import CoreStore
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - ListObserverTests
|
// MARK: - ListObserverTests
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
class ListObserverTests: BaseTestDataTestCase {
|
class ListObserverTests: BaseTestDataTestCase {
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -44,7 +43,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
let monitor = stack.monitorSectionedList(
|
let monitor = stack.monitorSectionedList(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||||
)
|
)
|
||||||
monitor.addObserver(observer)
|
monitor.addObserver(observer)
|
||||||
|
|
||||||
@@ -55,7 +54,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
var events = 0
|
var events = 0
|
||||||
|
|
||||||
let willChangeExpectation = self.expectation(
|
let willChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorWillChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didInsertSectionExpectation = self.expectation(
|
let didInsertSectionExpectation = self.expectation(
|
||||||
forNotification: "listMonitor:didInsertSection:toSectionIndex:",
|
forNotification: NSNotification.Name(rawValue: "listMonitor:didInsertSection:toSectionIndex:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -89,7 +88,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didInsertObjectExpectation = self.expectation(
|
let didInsertObjectExpectation = self.expectation(
|
||||||
forNotification: "listMonitor:didInsertObject:toIndexPath:",
|
forNotification: NSNotification.Name(rawValue: "listMonitor:didInsertObject:toIndexPath:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -103,8 +102,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
)
|
)
|
||||||
|
|
||||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||||
XCTAssertEqual(indexPath?.section, 0)
|
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||||
XCTAssertEqual(indexPath?.row, 0)
|
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||||
|
|
||||||
let object = userInfo?["object"] as? TestEntity1
|
let object = userInfo?["object"] as? TestEntity1
|
||||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||||
@@ -121,7 +120,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didChangeExpectation = self.expectation(
|
let didChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorDidChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -134,7 +133,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let saveExpectation = self.expectation(description: "save")
|
let saveExpectation = self.expectation(description: "save")
|
||||||
stack.beginAsynchronous { (transaction) in
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) -> Bool in
|
||||||
|
|
||||||
let object = transaction.create(Into<TestEntity1>())
|
let object = transaction.create(Into<TestEntity1>())
|
||||||
object.testBoolean = NSNumber(value: true)
|
object.testBoolean = NSNumber(value: true)
|
||||||
@@ -144,19 +144,18 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!
|
object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!
|
||||||
object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!
|
object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!
|
||||||
|
|
||||||
transaction.commit { (result) in
|
return transaction.hasChanges
|
||||||
|
},
|
||||||
|
success: { (hasChanges) in
|
||||||
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(let hasChanges):
|
|
||||||
XCTAssertTrue(hasChanges)
|
XCTAssertTrue(hasChanges)
|
||||||
saveExpectation.fulfill()
|
saveExpectation.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
case .failure:
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
self.waitAndCheckExpectations()
|
self.waitAndCheckExpectations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,7 +171,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
let monitor = stack.monitorSectionedList(
|
let monitor = stack.monitorSectionedList(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||||
)
|
)
|
||||||
monitor.addObserver(observer)
|
monitor.addObserver(observer)
|
||||||
|
|
||||||
@@ -186,7 +185,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
var events = 0
|
var events = 0
|
||||||
|
|
||||||
let willChangeExpectation = self.expectation(
|
let willChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorWillChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -199,10 +198,9 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
return events == 0
|
return events == 0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for _ in 1 ... 2 {
|
|
||||||
|
|
||||||
let didUpdateObjectExpectation = self.expectation(
|
let didUpdateObjectExpectation = self.expectation(
|
||||||
forNotification: "listMonitor:didUpdateObject:atIndexPath:",
|
forNotification: NSNotification.Name(rawValue: "listMonitor:didUpdateObject:atIndexPath:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -221,8 +219,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
switch object?.testEntityID {
|
switch object?.testEntityID {
|
||||||
|
|
||||||
case NSNumber(value: 101)?:
|
case NSNumber(value: 101)?:
|
||||||
XCTAssertEqual(indexPath?.section, 1)
|
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
|
||||||
XCTAssertEqual(indexPath?.row, 0)
|
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||||
|
|
||||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
|
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
|
||||||
@@ -232,8 +230,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
|
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
|
||||||
|
|
||||||
case NSNumber(value: 102)?:
|
case NSNumber(value: 102)?:
|
||||||
XCTAssertEqual(indexPath?.section, 0)
|
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||||
XCTAssertEqual(indexPath?.row, 0)
|
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||||
|
|
||||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
|
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
|
||||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
|
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
|
||||||
@@ -252,9 +250,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
return events == 1 || events == 2
|
return events == 1 || events == 2
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
let didChangeExpectation = self.expectation(
|
let didChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorDidChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -268,11 +265,12 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let saveExpectation = self.expectation(description: "save")
|
let saveExpectation = self.expectation(description: "save")
|
||||||
stack.beginAsynchronous { (transaction) in
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) -> Bool in
|
||||||
|
|
||||||
if let object = transaction.fetchOne(
|
if let object = transaction.fetchOne(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
|
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
|
||||||
|
|
||||||
object.testNumber = NSNumber(value: 11)
|
object.testNumber = NSNumber(value: 11)
|
||||||
object.testDecimal = NSDecimalNumber(string: "11")
|
object.testDecimal = NSDecimalNumber(string: "11")
|
||||||
@@ -286,7 +284,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
if let object = transaction.fetchOne(
|
if let object = transaction.fetchOne(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
||||||
|
|
||||||
object.testNumber = NSNumber(value: 22)
|
object.testNumber = NSNumber(value: 22)
|
||||||
object.testDecimal = NSDecimalNumber(string: "22")
|
object.testDecimal = NSDecimalNumber(string: "22")
|
||||||
@@ -298,19 +296,18 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.commit { (result) in
|
return transaction.hasChanges
|
||||||
|
},
|
||||||
|
success: { (hasChanges) in
|
||||||
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(let hasChanges):
|
|
||||||
XCTAssertTrue(hasChanges)
|
XCTAssertTrue(hasChanges)
|
||||||
saveExpectation.fulfill()
|
saveExpectation.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
case .failure:
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
self.waitAndCheckExpectations()
|
self.waitAndCheckExpectations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,14 +323,14 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
let monitor = stack.monitorSectionedList(
|
let monitor = stack.monitorSectionedList(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||||
)
|
)
|
||||||
monitor.addObserver(observer)
|
monitor.addObserver(observer)
|
||||||
|
|
||||||
var events = 0
|
var events = 0
|
||||||
|
|
||||||
let willChangeExpectation = self.expectation(
|
let willChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorWillChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -347,7 +344,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didMoveObjectExpectation = self.expectation(
|
let didMoveObjectExpectation = self.expectation(
|
||||||
forNotification: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:",
|
forNotification: NSNotification.Name(rawValue: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -361,12 +358,12 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
)
|
)
|
||||||
|
|
||||||
let fromIndexPath = userInfo?["fromIndexPath"] as? NSIndexPath
|
let fromIndexPath = userInfo?["fromIndexPath"] as? NSIndexPath
|
||||||
XCTAssertEqual(fromIndexPath?.section, 0)
|
XCTAssertEqual(fromIndexPath?.index(atPosition: 0), 0)
|
||||||
XCTAssertEqual(fromIndexPath?.row, 0)
|
XCTAssertEqual(fromIndexPath?.index(atPosition: 1), 0)
|
||||||
|
|
||||||
let toIndexPath = userInfo?["toIndexPath"] as? NSIndexPath
|
let toIndexPath = userInfo?["toIndexPath"] as? NSIndexPath
|
||||||
XCTAssertEqual(toIndexPath?.section, 1)
|
XCTAssertEqual(toIndexPath?.index(atPosition: 0), 1)
|
||||||
XCTAssertEqual(toIndexPath?.row, 1)
|
XCTAssertEqual(toIndexPath?.index(atPosition: 1), 1)
|
||||||
|
|
||||||
let object = userInfo?["object"] as? TestEntity1
|
let object = userInfo?["object"] as? TestEntity1
|
||||||
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
|
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
|
||||||
@@ -380,7 +377,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didChangeExpectation = self.expectation(
|
let didChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorDidChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -394,11 +391,12 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let saveExpectation = self.expectation(description: "save")
|
let saveExpectation = self.expectation(description: "save")
|
||||||
stack.beginAsynchronous { (transaction) in
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) -> Bool in
|
||||||
|
|
||||||
if let object = transaction.fetchOne(
|
if let object = transaction.fetchOne(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
||||||
|
|
||||||
object.testBoolean = NSNumber(value: true)
|
object.testBoolean = NSNumber(value: true)
|
||||||
}
|
}
|
||||||
@@ -406,19 +404,18 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
transaction.commit { (result) in
|
return transaction.hasChanges
|
||||||
|
},
|
||||||
|
success: { (hasChanges) in
|
||||||
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(let hasChanges):
|
|
||||||
XCTAssertTrue(hasChanges)
|
XCTAssertTrue(hasChanges)
|
||||||
saveExpectation.fulfill()
|
saveExpectation.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
case .failure:
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
self.waitAndCheckExpectations()
|
self.waitAndCheckExpectations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,14 +431,14 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
let monitor = stack.monitorSectionedList(
|
let monitor = stack.monitorSectionedList(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
SectionBy(#keyPath(TestEntity1.testBoolean)),
|
||||||
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
|
||||||
)
|
)
|
||||||
monitor.addObserver(observer)
|
monitor.addObserver(observer)
|
||||||
|
|
||||||
var events = 0
|
var events = 0
|
||||||
|
|
||||||
let willChangeExpectation = self.expectation(
|
let willChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorWillChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -454,10 +451,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
return events == 0
|
return events == 0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for _ in 1 ... 2 {
|
|
||||||
|
|
||||||
let didUpdateObjectExpectation = self.expectation(
|
let didUpdateObjectExpectation = self.expectation(
|
||||||
forNotification: "listMonitor:didDeleteObject:fromIndexPath:",
|
forNotification: NSNotification.Name(rawValue: "listMonitor:didDeleteObject:fromIndexPath:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -473,7 +468,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||||
|
|
||||||
XCTAssertEqual(indexPath?.section, 0)
|
XCTAssertEqual(indexPath?.section, 0)
|
||||||
XCTAssert(indexPath?.row == 0 || indexPath?.row == 1)
|
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
|
||||||
|
|
||||||
let object = userInfo?["object"] as? TestEntity1
|
let object = userInfo?["object"] as? TestEntity1
|
||||||
XCTAssertEqual(object?.isDeleted, true)
|
XCTAssertEqual(object?.isDeleted, true)
|
||||||
@@ -485,9 +480,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
return events == 1 || events == 2
|
return events == 1 || events == 2
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
let didDeleteSectionExpectation = self.expectation(
|
let didDeleteSectionExpectation = self.expectation(
|
||||||
forNotification: "listMonitor:didDeleteSection:fromSectionIndex:",
|
forNotification: NSNotification.Name(rawValue: "listMonitor:didDeleteSection:fromSectionIndex:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -515,7 +509,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didChangeExpectation = self.expectation(
|
let didChangeExpectation = self.expectation(
|
||||||
forNotification: "listMonitorDidChange:",
|
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -529,25 +523,26 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let saveExpectation = self.expectation(description: "save")
|
let saveExpectation = self.expectation(description: "save")
|
||||||
stack.beginAsynchronous { (transaction) in
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) -> Bool in
|
||||||
|
|
||||||
transaction.deleteAll(
|
let count = transaction.deleteAll(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
|
Where<TestEntity1>(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
|
||||||
)
|
)
|
||||||
transaction.commit { (result) in
|
XCTAssertEqual(count, 2)
|
||||||
|
return transaction.hasChanges
|
||||||
|
},
|
||||||
|
success: { (hasChanges) in
|
||||||
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(let hasChanges):
|
|
||||||
XCTAssertTrue(hasChanges)
|
XCTAssertTrue(hasChanges)
|
||||||
saveExpectation.fulfill()
|
saveExpectation.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
case .failure:
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
self.waitAndCheckExpectations()
|
self.waitAndCheckExpectations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -556,6 +551,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
// MARK: TestListObserver
|
// MARK: TestListObserver
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
class TestListObserver: ListSectionObserver {
|
class TestListObserver: ListSectionObserver {
|
||||||
|
|
||||||
// MARK: ListObserver
|
// MARK: ListObserver
|
||||||
@@ -678,5 +674,3 @@ class TestListObserver: ListSectionObserver {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ final class MigrationChainTests: XCTestCase {
|
|||||||
dynamic func test_ThatNilMigrationChains_HaveNoVersions() {
|
dynamic func test_ThatNilMigrationChains_HaveNoVersions() {
|
||||||
|
|
||||||
let chain: MigrationChain = nil
|
let chain: MigrationChain = nil
|
||||||
XCTAssertTrue(chain.valid)
|
XCTAssertTrue(chain.isValid)
|
||||||
XCTAssertTrue(chain.empty)
|
XCTAssertTrue(chain.isEmpty)
|
||||||
|
|
||||||
XCTAssertFalse(chain.contains("version1"))
|
XCTAssertFalse(chain.contains("version1"))
|
||||||
XCTAssertNil(chain.nextVersionFrom("version1"))
|
XCTAssertNil(chain.nextVersionFrom("version1"))
|
||||||
@@ -48,8 +48,8 @@ final class MigrationChainTests: XCTestCase {
|
|||||||
dynamic func test_ThatStringMigrationChains_HaveOneVersion() {
|
dynamic func test_ThatStringMigrationChains_HaveOneVersion() {
|
||||||
|
|
||||||
let chain: MigrationChain = "version1"
|
let chain: MigrationChain = "version1"
|
||||||
XCTAssertTrue(chain.valid)
|
XCTAssertTrue(chain.isValid)
|
||||||
XCTAssertTrue(chain.empty)
|
XCTAssertTrue(chain.isEmpty)
|
||||||
|
|
||||||
XCTAssertTrue(chain.contains("version1"))
|
XCTAssertTrue(chain.contains("version1"))
|
||||||
XCTAssertFalse(chain.contains("version2"))
|
XCTAssertFalse(chain.contains("version2"))
|
||||||
@@ -62,8 +62,8 @@ final class MigrationChainTests: XCTestCase {
|
|||||||
dynamic func test_ThatArrayMigrationChains_HaveLinearVersions() {
|
dynamic func test_ThatArrayMigrationChains_HaveLinearVersions() {
|
||||||
|
|
||||||
let chain: MigrationChain = ["version1", "version2", "version3", "version4"]
|
let chain: MigrationChain = ["version1", "version2", "version3", "version4"]
|
||||||
XCTAssertTrue(chain.valid)
|
XCTAssertTrue(chain.isValid)
|
||||||
XCTAssertFalse(chain.empty)
|
XCTAssertFalse(chain.isEmpty)
|
||||||
|
|
||||||
XCTAssertTrue(chain.contains("version1"))
|
XCTAssertTrue(chain.contains("version1"))
|
||||||
XCTAssertTrue(chain.contains("version2"))
|
XCTAssertTrue(chain.contains("version2"))
|
||||||
@@ -86,8 +86,8 @@ final class MigrationChainTests: XCTestCase {
|
|||||||
"version2": "version3",
|
"version2": "version3",
|
||||||
"version3": "version4"
|
"version3": "version4"
|
||||||
]
|
]
|
||||||
XCTAssertTrue(chain.valid)
|
XCTAssertTrue(chain.isValid)
|
||||||
XCTAssertFalse(chain.empty)
|
XCTAssertFalse(chain.isEmpty)
|
||||||
|
|
||||||
XCTAssertTrue(chain.contains("version1"))
|
XCTAssertTrue(chain.contains("version1"))
|
||||||
XCTAssertTrue(chain.contains("version2"))
|
XCTAssertTrue(chain.contains("version2"))
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10174" systemVersion="15F34" minimumToolsVersion="Xcode 4.3">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11759" systemVersion="16C67" minimumToolsVersion="Xcode 4.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||||
<entity name="TestEntity1AAA" representedClassName="CoreStoreTests.TestEntity1" syncable="YES">
|
<entity name="TestEntity1AAA" representedClassName="CoreStoreTests.TestEntity1" syncable="YES">
|
||||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
|
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||||
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
|
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
||||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
|
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
|
<attribute name="testNumber" optional="YES" attributeType="Integer 32" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="TestEntity2" representedClassName="CoreStoreTests.TestEntity2" syncable="YES">
|
<entity name="TestEntity2" representedClassName="CoreStoreTests.TestEntity2" syncable="YES">
|
||||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
|
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||||
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
|
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
||||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
|
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
|
<attribute name="testNumber" optional="YES" attributeType="Integer 32" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
</entity>
|
</entity>
|
||||||
<configuration name="Config1">
|
<configuration name="Config1">
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ import XCTest
|
|||||||
import CoreStore
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - ObjectObserverTests
|
// MARK: - ObjectObserverTests
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
class ObjectObserverTests: BaseTestDataTestCase {
|
class ObjectObserverTests: BaseTestDataTestCase {
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -44,7 +43,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
guard let object = stack.fetchOne(
|
guard let object = stack.fetchOne(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
|
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
@@ -59,7 +58,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
var events = 0
|
var events = 0
|
||||||
|
|
||||||
let willUpdateExpectation = self.expectation(
|
let willUpdateExpectation = self.expectation(
|
||||||
forNotification: "objectMonitor:willUpdateObject:",
|
forNotification: NSNotification.Name(rawValue: "objectMonitor:willUpdateObject:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let didUpdateExpectation = self.expectation(
|
let didUpdateExpectation = self.expectation(
|
||||||
forNotification: "objectMonitor:didUpdateObject:changedPersistentKeys:",
|
forNotification: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -105,29 +104,29 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let saveExpectation = self.expectation(description: "save")
|
let saveExpectation = self.expectation(description: "save")
|
||||||
stack.beginAsynchronous { (transaction) in
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) -> Bool in
|
||||||
|
|
||||||
guard let object = transaction.edit(object) else {
|
guard let object = transaction.edit(object) else {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
try transaction.cancel()
|
||||||
}
|
}
|
||||||
object.testNumber = NSNumber(value: 10)
|
object.testNumber = NSNumber(value: 10)
|
||||||
object.testString = "nil:TestEntity1:10"
|
object.testString = "nil:TestEntity1:10"
|
||||||
|
|
||||||
transaction.commit { (result) in
|
return transaction.hasChanges
|
||||||
|
},
|
||||||
|
success: { (hasChanges) in
|
||||||
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(let hasChanges):
|
|
||||||
XCTAssertTrue(hasChanges)
|
XCTAssertTrue(hasChanges)
|
||||||
saveExpectation.fulfill()
|
saveExpectation.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
case .failure:
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
self.waitAndCheckExpectations()
|
self.waitAndCheckExpectations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +140,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
guard let object = stack.fetchOne(
|
guard let object = stack.fetchOne(
|
||||||
From<TestEntity1>(),
|
From<TestEntity1>(),
|
||||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
|
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
@@ -156,7 +155,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
var events = 0
|
var events = 0
|
||||||
|
|
||||||
let didDeleteExpectation = self.expectation(
|
let didDeleteExpectation = self.expectation(
|
||||||
forNotification: "objectMonitor:didDeleteObject:",
|
forNotification: NSNotification.Name(rawValue: "objectMonitor:didDeleteObject:"),
|
||||||
object: observer,
|
object: observer,
|
||||||
handler: { (note) -> Bool in
|
handler: { (note) -> Bool in
|
||||||
|
|
||||||
@@ -173,29 +172,29 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let saveExpectation = self.expectation(description: "save")
|
let saveExpectation = self.expectation(description: "save")
|
||||||
stack.beginAsynchronous { (transaction) in
|
stack.perform(
|
||||||
|
asynchronous: { (transaction) -> Bool in
|
||||||
|
|
||||||
guard let object = transaction.edit(object) else {
|
guard let object = transaction.edit(object) else {
|
||||||
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
try transaction.cancel()
|
||||||
}
|
}
|
||||||
transaction.delete(object)
|
transaction.delete(object)
|
||||||
|
|
||||||
transaction.commit { (result) in
|
return transaction.hasChanges
|
||||||
|
},
|
||||||
|
success: { (hasChanges) in
|
||||||
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(let hasChanges):
|
|
||||||
XCTAssertTrue(hasChanges)
|
XCTAssertTrue(hasChanges)
|
||||||
XCTAssertTrue(monitor.isObjectDeleted)
|
XCTAssertTrue(monitor.isObjectDeleted)
|
||||||
saveExpectation.fulfill()
|
saveExpectation.fulfill()
|
||||||
|
},
|
||||||
|
failure: { _ in
|
||||||
|
|
||||||
case .failure:
|
|
||||||
XCTFail()
|
XCTFail()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
self.waitAndCheckExpectations()
|
self.waitAndCheckExpectations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,6 +203,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
// MARK: TestObjectObserver
|
// MARK: TestObjectObserver
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
class TestObjectObserver: ObjectObserver {
|
class TestObjectObserver: ObjectObserver {
|
||||||
|
|
||||||
typealias ObjectEntityType = TestEntity1
|
typealias ObjectEntityType = TestEntity1
|
||||||
@@ -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(
|
NotificationCenter.default.post(
|
||||||
name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),
|
name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),
|
||||||
@@ -242,5 +242,3 @@ class TestObjectObserver: ObjectObserver {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -38,21 +38,21 @@ final class OrderByTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let orderBy = OrderBy()
|
let orderBy = OrderBy<NSManagedObject>()
|
||||||
XCTAssertEqual(orderBy, OrderBy([NSSortDescriptor]()))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>([NSSortDescriptor]()))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key", ascending: false)))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(NSSortDescriptor(key: "key", ascending: false)))
|
||||||
XCTAssertTrue(orderBy.sortDescriptors.isEmpty)
|
XCTAssertTrue(orderBy.sortDescriptors.isEmpty)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
|
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
|
||||||
let orderBy = OrderBy(sortDescriptor)
|
let orderBy = OrderBy<NSManagedObject>(sortDescriptor)
|
||||||
XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
|
XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
|
||||||
XCTAssertEqual(orderBy, OrderBy(.ascending("key1")))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key2")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.descending("key1")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key1", ascending: false)))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(NSSortDescriptor(key: "key1", ascending: false)))
|
||||||
XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>([sortDescriptor]))
|
||||||
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
|
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
@@ -61,76 +61,76 @@ final class OrderByTests: XCTestCase {
|
|||||||
NSSortDescriptor(key: "key1", ascending: true),
|
NSSortDescriptor(key: "key1", ascending: true),
|
||||||
NSSortDescriptor(key: "key2", ascending: false)
|
NSSortDescriptor(key: "key2", ascending: false)
|
||||||
]
|
]
|
||||||
let orderBy = OrderBy(sortDescriptors)
|
let orderBy = OrderBy<NSManagedObject>(sortDescriptors)
|
||||||
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptors))
|
||||||
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
|
||||||
XCTAssertNotEqual(
|
XCTAssertNotEqual(
|
||||||
orderBy,
|
orderBy,
|
||||||
OrderBy(
|
OrderBy<NSManagedObject>(
|
||||||
[
|
[
|
||||||
NSSortDescriptor(key: "key1", ascending: false),
|
NSSortDescriptor(key: "key1", ascending: false),
|
||||||
NSSortDescriptor(key: "key2", ascending: false)
|
NSSortDescriptor(key: "key2", ascending: false)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .ascending("key2")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key3")))
|
||||||
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
|
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let orderBy = OrderBy(.ascending("key1"))
|
let orderBy = OrderBy<NSManagedObject>(.ascending("key1"))
|
||||||
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
|
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
|
||||||
XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptor))
|
||||||
XCTAssertEqual(orderBy, OrderBy(.ascending("key1")))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.descending("key1")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key2")))
|
||||||
XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>([sortDescriptor]))
|
||||||
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
|
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let orderBy = OrderBy(.ascending("key1"), .descending("key2"))
|
let orderBy = OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2"))
|
||||||
let sortDescriptors = [
|
let sortDescriptors = [
|
||||||
NSSortDescriptor(key: "key1", ascending: true),
|
NSSortDescriptor(key: "key1", ascending: true),
|
||||||
NSSortDescriptor(key: "key2", ascending: false)
|
NSSortDescriptor(key: "key2", ascending: false)
|
||||||
]
|
]
|
||||||
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptors))
|
||||||
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
|
||||||
XCTAssertNotEqual(
|
XCTAssertNotEqual(
|
||||||
orderBy,
|
orderBy,
|
||||||
OrderBy(
|
OrderBy<NSManagedObject>(
|
||||||
[
|
[
|
||||||
NSSortDescriptor(key: "key1", ascending: false),
|
NSSortDescriptor(key: "key1", ascending: false),
|
||||||
NSSortDescriptor(key: "key2", ascending: false)
|
NSSortDescriptor(key: "key2", ascending: false)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .ascending("key2")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key3")))
|
||||||
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
|
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sortKeys: [SortKey] = [.ascending("key1"), .descending("key2")]
|
let sortKeys: [OrderBy<NSManagedObject>.SortKey] = [.ascending("key1"), .descending("key2")]
|
||||||
let orderBy = OrderBy(sortKeys)
|
let orderBy = OrderBy<NSManagedObject>(sortKeys)
|
||||||
let sortDescriptors = [
|
let sortDescriptors = [
|
||||||
NSSortDescriptor(key: "key1", ascending: true),
|
NSSortDescriptor(key: "key1", ascending: true),
|
||||||
NSSortDescriptor(key: "key2", ascending: false)
|
NSSortDescriptor(key: "key2", ascending: false)
|
||||||
]
|
]
|
||||||
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptors))
|
||||||
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
|
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
|
||||||
XCTAssertNotEqual(
|
XCTAssertNotEqual(
|
||||||
orderBy,
|
orderBy,
|
||||||
OrderBy(
|
OrderBy<NSManagedObject>(
|
||||||
[
|
[
|
||||||
NSSortDescriptor(key: "key1", ascending: false),
|
NSSortDescriptor(key: "key1", ascending: false),
|
||||||
NSSortDescriptor(key: "key2", ascending: false)
|
NSSortDescriptor(key: "key2", ascending: false)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .ascending("key2")))
|
||||||
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
|
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key3")))
|
||||||
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
|
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,15 +138,15 @@ final class OrderByTests: XCTestCase {
|
|||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatOrderByClauseOperations_ComputeCorrectly() {
|
dynamic func test_ThatOrderByClauseOperations_ComputeCorrectly() {
|
||||||
|
|
||||||
let orderBy1 = OrderBy(.ascending("key1"))
|
let orderBy1 = OrderBy<NSManagedObject>(.ascending("key1"))
|
||||||
let orderBy2 = OrderBy(.descending("key2"))
|
let orderBy2 = OrderBy<NSManagedObject>(.descending("key2"))
|
||||||
let orderBy3 = OrderBy(.ascending("key3"))
|
let orderBy3 = OrderBy<NSManagedObject>(.ascending("key3"))
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let plusOrderBy = orderBy1 + orderBy2 + orderBy3
|
let plusOrderBy = orderBy1 + orderBy2 + orderBy3
|
||||||
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3")))
|
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2"), .ascending("key3")))
|
||||||
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2"), .ascending("key3")))
|
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1")) + OrderBy<NSManagedObject>(.descending("key2"), .ascending("key3")))
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
|
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
|
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
|
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
|
||||||
@@ -158,14 +158,14 @@ final class OrderByTests: XCTestCase {
|
|||||||
|
|
||||||
var plusOrderBy = orderBy1
|
var plusOrderBy = orderBy1
|
||||||
plusOrderBy += orderBy2
|
plusOrderBy += orderBy2
|
||||||
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")))
|
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
|
||||||
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2")))
|
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1")) + OrderBy<NSManagedObject>(.descending("key2")))
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1)
|
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1)
|
||||||
XCTAssertEqual(plusOrderBy.sortDescriptors, orderBy1.sortDescriptors + orderBy2.sortDescriptors)
|
XCTAssertEqual(plusOrderBy.sortDescriptors, orderBy1.sortDescriptors + orderBy2.sortDescriptors)
|
||||||
|
|
||||||
plusOrderBy += orderBy3
|
plusOrderBy += orderBy3
|
||||||
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3")))
|
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2"), .ascending("key3")))
|
||||||
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")) + OrderBy(.ascending("key3")))
|
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")) + OrderBy<NSManagedObject>(.ascending("key3")))
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
|
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
|
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
|
||||||
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
|
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
|
||||||
@@ -178,7 +178,7 @@ final class OrderByTests: XCTestCase {
|
|||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
|
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
|
||||||
|
|
||||||
let orderBy = OrderBy(.ascending("key"))
|
let orderBy = OrderBy<NSManagedObject>(.ascending("key"))
|
||||||
let request = CoreStoreFetchRequest()
|
let request = CoreStoreFetchRequest()
|
||||||
orderBy.applyToFetchRequest(request)
|
orderBy.applyToFetchRequest(request)
|
||||||
XCTAssertNotNil(request.sortDescriptors)
|
XCTAssertNotNil(request.sortDescriptors)
|
||||||
|
|||||||
+140
-140
File diff suppressed because it is too large
Load Diff
@@ -29,10 +29,9 @@ import XCTest
|
|||||||
import CoreStore
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
//MARK: - SectionByTests
|
//MARK: - SectionByTests
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
final class SectionByTests: XCTestCase {
|
final class SectionByTests: XCTestCase {
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@@ -40,18 +39,16 @@ final class SectionByTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sectionBy = SectionBy("key")
|
let sectionBy = SectionBy<NSManagedObject>("key")
|
||||||
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
|
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
|
||||||
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
|
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } }
|
let sectionBy = SectionBy<NSManagedObject>("key") { $0.flatMap { "\($0):suffix" } }
|
||||||
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
|
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
|
||||||
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
|
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
|
||||||
XCTAssertNil(sectionBy.sectionIndexTransformer(nil))
|
XCTAssertNil(sectionBy.sectionIndexTransformer(nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term: SelectTerm = "attribute"
|
let term: SelectTerm<NSManagedObject> = "attribute"
|
||||||
XCTAssertEqual(term, SelectTerm.attribute("attribute"))
|
XCTAssertEqual(term, SelectTerm.attribute("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
|
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
|
||||||
@@ -58,7 +58,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.attribute("attribute")
|
let term = SelectTerm<NSManagedObject>.attribute("attribute")
|
||||||
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
|
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
|
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
|
||||||
@@ -82,7 +82,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.average("attribute")
|
let term = SelectTerm<NSManagedObject>.average("attribute")
|
||||||
XCTAssertEqual(term, SelectTerm.average("attribute"))
|
XCTAssertEqual(term, SelectTerm.average("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias"))
|
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
|
||||||
@@ -106,7 +106,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.average("attribute", as: "alias")
|
let term = SelectTerm<NSManagedObject>.average("attribute", as: "alias")
|
||||||
XCTAssertEqual(term, SelectTerm.average("attribute", as: "alias"))
|
XCTAssertEqual(term, SelectTerm.average("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias2"))
|
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
|
||||||
@@ -135,7 +135,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.count("attribute")
|
let term = SelectTerm<NSManagedObject>.count("attribute")
|
||||||
XCTAssertEqual(term, SelectTerm.count("attribute"))
|
XCTAssertEqual(term, SelectTerm.count("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias"))
|
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
|
||||||
@@ -159,7 +159,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.count("attribute", as: "alias")
|
let term = SelectTerm<NSManagedObject>.count("attribute", as: "alias")
|
||||||
XCTAssertEqual(term, SelectTerm.count("attribute", as: "alias"))
|
XCTAssertEqual(term, SelectTerm.count("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias2"))
|
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
|
||||||
@@ -188,7 +188,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.maximum("attribute")
|
let term = SelectTerm<NSManagedObject>.maximum("attribute")
|
||||||
XCTAssertEqual(term, SelectTerm.maximum("attribute"))
|
XCTAssertEqual(term, SelectTerm.maximum("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias"))
|
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
|
||||||
@@ -212,7 +212,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.maximum("attribute", as: "alias")
|
let term = SelectTerm<NSManagedObject>.maximum("attribute", as: "alias")
|
||||||
XCTAssertEqual(term, SelectTerm.maximum("attribute", as: "alias"))
|
XCTAssertEqual(term, SelectTerm.maximum("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias2"))
|
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
|
||||||
@@ -241,7 +241,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.minimum("attribute")
|
let term = SelectTerm<NSManagedObject>.minimum("attribute")
|
||||||
XCTAssertEqual(term, SelectTerm.minimum("attribute"))
|
XCTAssertEqual(term, SelectTerm.minimum("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias"))
|
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
|
||||||
@@ -265,7 +265,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.minimum("attribute", as: "alias")
|
let term = SelectTerm<NSManagedObject>.minimum("attribute", as: "alias")
|
||||||
XCTAssertEqual(term, SelectTerm.minimum("attribute", as: "alias"))
|
XCTAssertEqual(term, SelectTerm.minimum("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias2"))
|
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
|
||||||
@@ -294,7 +294,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.sum("attribute")
|
let term = SelectTerm<NSManagedObject>.sum("attribute")
|
||||||
XCTAssertEqual(term, SelectTerm.sum("attribute"))
|
XCTAssertEqual(term, SelectTerm.sum("attribute"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias"))
|
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
|
||||||
@@ -318,7 +318,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.sum("attribute", as: "alias")
|
let term = SelectTerm<NSManagedObject>.sum("attribute", as: "alias")
|
||||||
XCTAssertEqual(term, SelectTerm.sum("attribute", as: "alias"))
|
XCTAssertEqual(term, SelectTerm.sum("attribute", as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias2"))
|
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
|
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
|
||||||
@@ -347,7 +347,7 @@ final class SelectTests: XCTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.objectID()
|
let term = SelectTerm<NSManagedObject>.objectID()
|
||||||
XCTAssertEqual(term, SelectTerm.objectID())
|
XCTAssertEqual(term, SelectTerm.objectID())
|
||||||
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias"))
|
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
|
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
|
||||||
@@ -368,7 +368,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let term = SelectTerm.objectID(as: "alias")
|
let term = SelectTerm<NSManagedObject>.objectID(as: "alias")
|
||||||
XCTAssertEqual(term, SelectTerm.objectID(as: "alias"))
|
XCTAssertEqual(term, SelectTerm.objectID(as: "alias"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias2"))
|
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias2"))
|
||||||
XCTAssertNotEqual(term, SelectTerm.objectID())
|
XCTAssertNotEqual(term, SelectTerm.objectID())
|
||||||
@@ -393,12 +393,12 @@ final class SelectTests: XCTestCase {
|
|||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatSelectClauses_ConfigureCorrectly() {
|
dynamic func test_ThatSelectClauses_ConfigureCorrectly() {
|
||||||
|
|
||||||
let term1 = SelectTerm.attribute("attribute1")
|
let term1 = SelectTerm<NSManagedObject>.attribute("attribute1")
|
||||||
let term2 = SelectTerm.attribute("attribute2")
|
let term2 = SelectTerm<NSManagedObject>.attribute("attribute2")
|
||||||
let term3 = SelectTerm.attribute("attribute3")
|
let term3 = SelectTerm<NSManagedObject>.attribute("attribute3")
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let select = Select<Int>(term1, term2, term3)
|
let select = Select<NSManagedObject, Int>(term1, term2, term3)
|
||||||
XCTAssertEqual(select.selectTerms, [term1, term2, term3])
|
XCTAssertEqual(select.selectTerms, [term1, term2, term3])
|
||||||
XCTAssertNotEqual(select.selectTerms, [term1, term3, term2])
|
XCTAssertNotEqual(select.selectTerms, [term1, term3, term2])
|
||||||
XCTAssertNotEqual(select.selectTerms, [term2, term1, term3])
|
XCTAssertNotEqual(select.selectTerms, [term2, term1, term3])
|
||||||
@@ -408,7 +408,7 @@ final class SelectTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let select = Select<Int>([term1, term2, term3])
|
let select = Select<NSManagedObject, Int>([term1, term2, term3])
|
||||||
XCTAssertEqual(select.selectTerms, [term1, term2, term3])
|
XCTAssertEqual(select.selectTerms, [term1, term2, term3])
|
||||||
XCTAssertNotEqual(select.selectTerms, [term1, term3, term2])
|
XCTAssertNotEqual(select.selectTerms, [term1, term3, term2])
|
||||||
XCTAssertNotEqual(select.selectTerms, [term2, term1, term3])
|
XCTAssertNotEqual(select.selectTerms, [term2, term1, term3])
|
||||||
|
|||||||
@@ -36,10 +36,14 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let model = NSManagedObjectModel.mergedModel(from: [Bundle(for: type(of: self))])!
|
let schemaHistory = SchemaHistory(
|
||||||
|
XcodeDataModelSchema.from(
|
||||||
let stack = DataStack(model: model, migrationChain: nil)
|
modelName: "Model",
|
||||||
XCTAssertEqual(stack.coordinator.managedObjectModel, model)
|
bundle: Bundle(for: type(of: self))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
let stack = DataStack(schemaHistory: schemaHistory)
|
||||||
|
XCTAssertEqual(stack.coordinator.managedObjectModel, schemaHistory.rawModel)
|
||||||
XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator)
|
XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator)
|
||||||
XCTAssertNil(stack.rootSavingContext.parent)
|
XCTAssertNil(stack.rootSavingContext.parent)
|
||||||
XCTAssertFalse(stack.rootSavingContext.isDataStackContext)
|
XCTAssertFalse(stack.rootSavingContext.isDataStackContext)
|
||||||
@@ -47,29 +51,29 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext)
|
XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext)
|
||||||
XCTAssertTrue(stack.mainContext.isDataStackContext)
|
XCTAssertTrue(stack.mainContext.isDataStackContext)
|
||||||
XCTAssertFalse(stack.mainContext.isTransactionContext)
|
XCTAssertFalse(stack.mainContext.isTransactionContext)
|
||||||
XCTAssertEqual(stack.model, model)
|
XCTAssertEqual(stack.schemaHistory.rawModel, schemaHistory.rawModel)
|
||||||
XCTAssertTrue(stack.migrationChain.valid)
|
XCTAssertTrue(stack.schemaHistory.migrationChain.isValid)
|
||||||
XCTAssertTrue(stack.migrationChain.empty)
|
XCTAssertTrue(stack.schemaHistory.migrationChain.isEmpty)
|
||||||
XCTAssertTrue(stack.migrationChain.rootVersions.isEmpty)
|
XCTAssertTrue(stack.schemaHistory.migrationChain.rootVersions.isEmpty)
|
||||||
XCTAssertTrue(stack.migrationChain.leafVersions.isEmpty)
|
XCTAssertTrue(stack.schemaHistory.migrationChain.leafVersions.isEmpty)
|
||||||
|
|
||||||
CoreStore.defaultStack = stack
|
CoreStore.defaultStack = stack
|
||||||
XCTAssertEqual(CoreStore.defaultStack, stack)
|
XCTAssertEqual(CoreStore.defaultStack, stack)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let migrationChain: MigrationChain = ["version1", "version2", "version3"]
|
let migrationChain: MigrationChain = ["version1", "version2", "version3", "Model"]
|
||||||
|
|
||||||
let stack = self.expectLogger([.logWarning]) {
|
let stack = self.expectLogger([.logWarning]) {
|
||||||
|
|
||||||
DataStack(
|
DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self)),
|
bundle: Bundle(for: type(of: self)),
|
||||||
migrationChain: migrationChain
|
migrationChain: migrationChain
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
XCTAssertEqual(stack.modelVersion, "Model")
|
XCTAssertEqual(stack.modelVersion, "Model")
|
||||||
XCTAssertEqual(stack.migrationChain, migrationChain)
|
XCTAssertEqual(stack.schemaHistory.migrationChain, migrationChain)
|
||||||
|
|
||||||
CoreStore.defaultStack = stack
|
CoreStore.defaultStack = stack
|
||||||
XCTAssertEqual(CoreStore.defaultStack, stack)
|
XCTAssertEqual(CoreStore.defaultStack, stack)
|
||||||
@@ -80,7 +84,7 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
dynamic func test_ThatInMemoryStores_SetupCorrectly() {
|
dynamic func test_ThatInMemoryStores_SetupCorrectly() {
|
||||||
|
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
do {
|
do {
|
||||||
@@ -135,7 +139,7 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
dynamic func test_ThatSQLiteStores_SetupCorrectly() {
|
dynamic func test_ThatSQLiteStores_SetupCorrectly() {
|
||||||
|
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
do {
|
do {
|
||||||
@@ -203,14 +207,13 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
do {
|
do {
|
||||||
|
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
try! stack.addStorageAndWait(sqliteStore)
|
try! stack.addStorageAndWait(sqliteStore)
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
}
|
}
|
||||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
|
||||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||||
|
|
||||||
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||||
@@ -223,10 +226,13 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
let metadata = try createStore()
|
let metadata = try createStore()
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata])
|
try sqliteStore.cs_eraseStorageAndWait(
|
||||||
|
metadata: metadata,
|
||||||
|
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
|
||||||
|
)
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||||
@@ -238,7 +244,7 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
do {
|
do {
|
||||||
|
|
||||||
let metadata = try createStore()
|
let metadata = try createStore()
|
||||||
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
|
try sqliteStore.cs_eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||||
@@ -253,12 +259,12 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
|
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
|
||||||
|
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sqliteStore = LegacySQLiteStore()
|
let sqliteStore = SQLiteStore.legacy()
|
||||||
do {
|
do {
|
||||||
|
|
||||||
try stack.addStorageAndWait(sqliteStore)
|
try stack.addStorageAndWait(sqliteStore)
|
||||||
@@ -273,7 +279,7 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sqliteStore = LegacySQLiteStore(
|
let sqliteStore = SQLiteStore.legacy(
|
||||||
fileName: "ConfigStore1.sqlite",
|
fileName: "ConfigStore1.sqlite",
|
||||||
configuration: "Config1",
|
configuration: "Config1",
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
@@ -292,7 +298,7 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let sqliteStore = LegacySQLiteStore(
|
let sqliteStore = SQLiteStore.legacy(
|
||||||
fileName: "ConfigStore2.sqlite",
|
fileName: "ConfigStore2.sqlite",
|
||||||
configuration: "Config2",
|
configuration: "Config2",
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
@@ -315,20 +321,19 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
dynamic func test_ThatLegacySQLiteStores_DeleteFilesCorrectly() {
|
dynamic func test_ThatLegacySQLiteStores_DeleteFilesCorrectly() {
|
||||||
|
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
let sqliteStore = LegacySQLiteStore()
|
let sqliteStore = SQLiteStore.legacy()
|
||||||
func createStore() throws -> [String: Any] {
|
func createStore() throws -> [String: Any] {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
try! stack.addStorageAndWait(sqliteStore)
|
try! stack.addStorageAndWait(sqliteStore)
|
||||||
self.prepareTestDataForStack(stack)
|
self.prepareTestDataForStack(stack)
|
||||||
}
|
}
|
||||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
|
||||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||||
|
|
||||||
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||||
@@ -341,10 +346,13 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
|
|
||||||
let metadata = try createStore()
|
let metadata = try createStore()
|
||||||
let stack = DataStack(
|
let stack = DataStack(
|
||||||
modelName: "Model",
|
xcodeModelName: "Model",
|
||||||
bundle: Bundle(for: type(of: self))
|
bundle: Bundle(for: type(of: self))
|
||||||
)
|
)
|
||||||
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata])
|
try sqliteStore.cs_eraseStorageAndWait(
|
||||||
|
metadata: metadata,
|
||||||
|
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
|
||||||
|
)
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||||
@@ -356,7 +364,7 @@ class SetupTests: BaseTestDataTestCase {
|
|||||||
do {
|
do {
|
||||||
|
|
||||||
let metadata = try createStore()
|
let metadata = try createStore()
|
||||||
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
|
try sqliteStore.cs_eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ final class StorageInterfaceTests: XCTestCase {
|
|||||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||||
|
|
||||||
XCTAssertEqual(store.fileURL, SQLiteStore.defaultFileURL)
|
XCTAssertEqual(store.fileURL, SQLiteStore.defaultFileURL)
|
||||||
XCTAssertEqual(store.mappingModelBundles, Bundle.allBundles)
|
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
|
||||||
XCTAssertEqual(store.localStorageOptions, .none)
|
XCTAssertEqual(store.localStorageOptions, .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,12 +96,15 @@ final class StorageInterfaceTests: XCTestCase {
|
|||||||
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
|
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
|
||||||
.appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
|
.appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
|
||||||
.appendingPathExtension("db")
|
.appendingPathExtension("db")
|
||||||
let bundles = [Bundle(for: type(of: self))]
|
let mappingProvider = XcodeSchemaMappingProvider(
|
||||||
|
from: "V1", to: "V2",
|
||||||
|
mappingModelBundle: Bundle(for: type(of: self))
|
||||||
|
)
|
||||||
|
|
||||||
let store = SQLiteStore(
|
let store = SQLiteStore(
|
||||||
fileURL: fileURL,
|
fileURL: fileURL,
|
||||||
configuration: "config1",
|
configuration: "config1",
|
||||||
mappingModelBundles: bundles,
|
migrationMappingProviders: [mappingProvider],
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
)
|
)
|
||||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||||
@@ -109,7 +112,7 @@ final class StorageInterfaceTests: XCTestCase {
|
|||||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||||
|
|
||||||
XCTAssertEqual(store.fileURL, fileURL)
|
XCTAssertEqual(store.fileURL, fileURL)
|
||||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
|
||||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,12 +120,14 @@ final class StorageInterfaceTests: XCTestCase {
|
|||||||
dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() {
|
dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() {
|
||||||
|
|
||||||
let fileName = UUID().uuidString + ".db"
|
let fileName = UUID().uuidString + ".db"
|
||||||
let bundles = [Bundle(for: type(of: self))]
|
let mappingProvider = XcodeSchemaMappingProvider(
|
||||||
|
from: "V1", to: "V2",
|
||||||
|
mappingModelBundle: Bundle(for: type(of: self))
|
||||||
|
)
|
||||||
let store = SQLiteStore(
|
let store = SQLiteStore(
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
configuration: "config1",
|
configuration: "config1",
|
||||||
mappingModelBundles: bundles,
|
migrationMappingProviders: [mappingProvider],
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
)
|
)
|
||||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||||
@@ -131,7 +136,7 @@ final class StorageInterfaceTests: XCTestCase {
|
|||||||
|
|
||||||
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.defaultRootDirectory)
|
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.defaultRootDirectory)
|
||||||
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
|
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
|
||||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
|
||||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,65 +157,44 @@ final class StorageInterfaceTests: XCTestCase {
|
|||||||
.appendingPathComponent(DataStack.applicationName, isDirectory: false)
|
.appendingPathComponent(DataStack.applicationName, isDirectory: false)
|
||||||
.appendingPathExtension("sqlite")
|
.appendingPathExtension("sqlite")
|
||||||
|
|
||||||
XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory)
|
XCTAssertEqual(SQLiteStore.legacyDefaultRootDirectory, legacyDefaultRootDirectory)
|
||||||
XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL)
|
XCTAssertEqual(SQLiteStore.legacyDefaultFileURL, legacyDefaultFileURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() {
|
dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() {
|
||||||
|
|
||||||
let store = LegacySQLiteStore()
|
let store = SQLiteStore.legacy()
|
||||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||||
XCTAssertNil(store.configuration)
|
XCTAssertNil(store.configuration)
|
||||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||||
|
|
||||||
XCTAssertEqual(store.fileURL, LegacySQLiteStore.defaultFileURL)
|
XCTAssertEqual(store.fileURL, SQLiteStore.legacyDefaultFileURL)
|
||||||
XCTAssertEqual(store.mappingModelBundles, Bundle.allBundles)
|
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
|
||||||
XCTAssertEqual(store.localStorageOptions, .none)
|
XCTAssertEqual(store.localStorageOptions, .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
|
||||||
dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() {
|
|
||||||
|
|
||||||
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
|
|
||||||
.appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
|
|
||||||
.appendingPathExtension("db")
|
|
||||||
let bundles = [Bundle(for: type(of: self))]
|
|
||||||
|
|
||||||
let store = LegacySQLiteStore(
|
|
||||||
fileURL: fileURL,
|
|
||||||
configuration: "config1",
|
|
||||||
mappingModelBundles: bundles,
|
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
|
||||||
)
|
|
||||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
|
||||||
XCTAssertEqual(store.configuration, "config1")
|
|
||||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
|
||||||
|
|
||||||
XCTAssertEqual(store.fileURL, fileURL)
|
|
||||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
|
||||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() {
|
dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() {
|
||||||
|
|
||||||
let fileName = UUID().uuidString + ".db"
|
let fileName = UUID().uuidString + ".db"
|
||||||
let bundles = [Bundle(for: type(of: self))]
|
let mappingProvider = XcodeSchemaMappingProvider(
|
||||||
|
from: "V1", to: "V2",
|
||||||
let store = LegacySQLiteStore(
|
mappingModelBundle: Bundle(for: type(of: self))
|
||||||
|
)
|
||||||
|
let store = SQLiteStore.legacy(
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
configuration: "config1",
|
configuration: "config1",
|
||||||
mappingModelBundles: bundles,
|
migrationMappingProviders: [mappingProvider],
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
)
|
)
|
||||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||||
XCTAssertEqual(store.configuration, "config1")
|
XCTAssertEqual(store.configuration, "config1")
|
||||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||||
|
|
||||||
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), LegacySQLiteStore.defaultRootDirectory)
|
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.legacyDefaultRootDirectory)
|
||||||
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
|
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
|
||||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
|
||||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+155
-188
@@ -29,60 +29,85 @@ import XCTest
|
|||||||
import CoreStore
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - XCTAssertAllEqual
|
||||||
|
|
||||||
|
private func XCTAssertAllEqual<D>(_ whereClauses: Where<D>...) {
|
||||||
|
|
||||||
|
XCTAssertAllEqual(whereClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func XCTAssertAllEqual<D>(_ whereClauses: [Where<D>]) {
|
||||||
|
|
||||||
|
for i in whereClauses.indices {
|
||||||
|
|
||||||
|
for j in whereClauses.indices where j != i {
|
||||||
|
|
||||||
|
XCTAssertEqual(whereClauses[i], whereClauses[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//MARK: - WhereTests
|
//MARK: - WhereTests
|
||||||
|
|
||||||
final class WhereTests: XCTestCase {
|
final class WhereTests: XCTestCase {
|
||||||
|
|
||||||
|
@objc
|
||||||
|
dynamic func test_ThatDynamicModelKeyPaths_CanBeCreated() {
|
||||||
|
|
||||||
|
XCTAssertEqual(String(keyPath: \TestEntity1.testEntityID), "testEntityID")
|
||||||
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatWhereClauses_ConfigureCorrectly() {
|
dynamic func test_ThatWhereClauses_ConfigureCorrectly() {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let whereClause = Where()
|
let whereClause = Where<NSManagedObject>()
|
||||||
XCTAssertEqual(whereClause, Where(true))
|
XCTAssertEqual(whereClause, Where<NSManagedObject>(true))
|
||||||
XCTAssertNotEqual(whereClause, Where(false))
|
XCTAssertNotEqual(whereClause, Where<NSManagedObject>(false))
|
||||||
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
|
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let whereClause = Where(true)
|
let whereClause = Where<NSManagedObject>(true)
|
||||||
XCTAssertEqual(whereClause, Where())
|
XCTAssertEqual(whereClause, Where<NSManagedObject>())
|
||||||
XCTAssertNotEqual(whereClause, Where(false))
|
XCTAssertNotEqual(whereClause, Where<NSManagedObject>(false))
|
||||||
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
|
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
||||||
let whereClause = Where(predicate)
|
let whereClause = Where<NSManagedObject>(predicate)
|
||||||
XCTAssertEqual(whereClause, Where(predicate))
|
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
|
||||||
XCTAssertEqual(whereClause.predicate, predicate)
|
XCTAssertEqual(whereClause.predicate, predicate)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let whereClause = Where("%K == %@", "key", "value")
|
let whereClause = Where<NSManagedObject>("%K == %@", "key", "value")
|
||||||
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
||||||
XCTAssertEqual(whereClause, Where(predicate))
|
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
|
||||||
XCTAssertEqual(whereClause.predicate, predicate)
|
XCTAssertEqual(whereClause.predicate, predicate)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let whereClause = Where("%K == %@", argumentArray: ["key", "value"])
|
let whereClause = Where<NSManagedObject>("%K == %@", argumentArray: ["key", "value"])
|
||||||
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
||||||
XCTAssertEqual(whereClause, Where(predicate))
|
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
|
||||||
XCTAssertEqual(whereClause.predicate, predicate)
|
XCTAssertEqual(whereClause.predicate, predicate)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let whereClause = Where("key", isEqualTo: "value")
|
let whereClause = Where<NSManagedObject>("key", isEqualTo: "value")
|
||||||
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
let predicate = NSPredicate(format: "%K == %@", "key", "value")
|
||||||
XCTAssertEqual(whereClause, Where(predicate))
|
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
|
||||||
XCTAssertEqual(whereClause.predicate, predicate)
|
XCTAssertEqual(whereClause.predicate, predicate)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let whereClause = Where("key", isMemberOf: ["value1", "value2", "value3"])
|
let whereClause = Where<NSManagedObject>("key", isMemberOf: ["value1", "value2", "value3"])
|
||||||
let predicate = NSPredicate(format: "%K IN %@", "key", ["value1", "value2", "value3"])
|
let predicate = NSPredicate(format: "%K IN %@", "key", ["value1", "value2", "value3"])
|
||||||
XCTAssertEqual(whereClause, Where(predicate))
|
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
|
||||||
XCTAssertEqual(whereClause.predicate, predicate)
|
XCTAssertEqual(whereClause.predicate, predicate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,211 +118,123 @@ final class WhereTests: XCTestCase {
|
|||||||
do {
|
do {
|
||||||
|
|
||||||
let value: Int = 100
|
let value: Int = 100
|
||||||
let whereClause1 = Where("%K == %d", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %d", "key", value),
|
||||||
let whereClause3 = Where("%K == %d", "key", NSNumber(value: value))
|
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value)
|
Where<NSManagedObject>("%K == %d", "key", NSNumber(value: value)),
|
||||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %@", "key", value),
|
||||||
let whereClause6 = Where("%K == %@", "key", NSNumber(value: value))
|
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K == %@", "key", NSNumber(value: value)),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isEqualTo: value),
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
Where<NSManagedObject>("key", isEqualTo: NSNumber(value: value))
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
)
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value = NSNumber(value: 100)
|
let value = NSNumber(value: 100)
|
||||||
let whereClause1 = Where("%K == %d", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %d", "key", value),
|
||||||
let whereClause3 = Where("%K == %d", "key", value.intValue)
|
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value)
|
Where<NSManagedObject>("%K == %d", "key", value.intValue),
|
||||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %@", "key", value),
|
||||||
let whereClause6 = Where("%K == %@", "key", value.intValue)
|
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K == %@", "key", value.intValue),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isEqualTo: value),
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
Where<NSManagedObject>("key", isEqualTo: value.intValue)
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
)
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value: Int64 = Int64.max
|
let value: Int64 = Int64.max
|
||||||
let whereClause1 = Where("%K == %d", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %d", "key", value),
|
||||||
let whereClause3 = Where("%K == %d", "key", NSNumber(value: value))
|
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value)
|
Where<NSManagedObject>("%K == %d", "key", NSNumber(value: value)),
|
||||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %@", "key", value),
|
||||||
let whereClause6 = Where("%K == %@", "key", NSNumber(value: value))
|
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K == %@", "key", NSNumber(value: value)),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isEqualTo: value),
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
Where<NSManagedObject>("key", isEqualTo: NSNumber(value: value))
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
)
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value = NSNumber(value: Int64.max)
|
let value = NSNumber(value: Int64.max)
|
||||||
let whereClause1 = Where("%K == %d", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %d", "key", value),
|
||||||
let whereClause3 = Where("%K == %d", "key", value.int64Value)
|
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value)
|
Where<NSManagedObject>("%K == %d", "key", value.int64Value),
|
||||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %@", "key", value),
|
||||||
let whereClause6 = Where("%K == %@", "key", value.int64Value)
|
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K == %@", "key", value.int64Value),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isEqualTo: value),
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
Where<NSManagedObject>("key", isEqualTo: value.int64Value)
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
)
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value: String = "value"
|
let value: String = "value"
|
||||||
let whereClause1 = Where("%K == %s", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %s", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %s", "key", value),
|
||||||
let whereClause3 = Where("%K == %s", "key", NSString(string: value))
|
Where<NSManagedObject>("%K == %s", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value)
|
Where<NSManagedObject>("%K == %s", "key", NSString(string: value)),
|
||||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K == %@", "key", value),
|
||||||
let whereClause6 = Where("%K == %@", "key", NSString(string: value))
|
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K == %@", "key", NSString(string: value)),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isEqualTo: value),
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
Where<NSManagedObject>("key", isEqualTo: value as NSString),
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
Where<NSManagedObject>("key", isEqualTo: NSString(string: value))
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
)
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value = NSString(string: "value")
|
let value = NSString(string: "value")
|
||||||
let whereClause1 = Where("%K == %s", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %s", "key", value as String)
|
Where<NSManagedObject>("%K == %s", "key", value),
|
||||||
let whereClause3 = Where("%K == %s", "key", value as String as AnyObject)
|
Where<NSManagedObject>("%K == %s", "key", value as String),
|
||||||
let whereClause4 = Where("%K == %@", "key", value)
|
Where<NSManagedObject>("%K == %s", "key", value as String as AnyObject),
|
||||||
let whereClause5 = Where("%K == %@", "key", value as String)
|
Where<NSManagedObject>("%K == %@", "key", value),
|
||||||
let whereClause6 = Where("%K == %@", "key", value as String as AnyObject)
|
Where<NSManagedObject>("%K == %@", "key", value as String),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K == %@", "key", value as String as AnyObject),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isEqualTo: value),
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
Where<NSManagedObject>("key", isEqualTo: value as String),
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
Where<NSManagedObject>("key", isEqualTo: value as String as NSString)
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
)
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value: [Int] = [100, 200]
|
let value: [Int] = [100, 200]
|
||||||
let whereClause1 = Where("%K == %@", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K IN %@", "key", value),
|
||||||
let whereClause3 = Where("%K == %@", "key", value as [AnyObject])
|
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value as NSArray)
|
Where<NSManagedObject>("%K IN %@", "key", value as [AnyObject]),
|
||||||
let whereClause5 = Where("%K == %@", "key", NSArray(array: value))
|
Where<NSManagedObject>("%K IN %@", "key", value as NSArray),
|
||||||
let whereClause6 = Where("%K == %@", "key", value as AnyObject as! NSArray)
|
Where<NSManagedObject>("%K IN %@", "key", NSArray(array: value)),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject as! NSArray),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isMemberOf: value)
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
)
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let value: [Int64] = [Int64.min, 100, Int64.max]
|
let value: [Int64] = [Int64.min, 100, Int64.max]
|
||||||
let whereClause1 = Where("%K == %@", "key", value)
|
XCTAssertAllEqual(
|
||||||
let whereClause2 = Where("%K == %@", "key", value as AnyObject)
|
Where<NSManagedObject>("%K IN %@", "key", value),
|
||||||
let whereClause3 = Where("%K == %@", "key", value as [AnyObject])
|
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject),
|
||||||
let whereClause4 = Where("%K == %@", "key", value as NSArray)
|
Where<NSManagedObject>("%K IN %@", "key", value as [AnyObject]),
|
||||||
let whereClause5 = Where("%K == %@", "key", NSArray(array: value))
|
Where<NSManagedObject>("%K IN %@", "key", value as NSArray),
|
||||||
let whereClause6 = Where("%K == %@", "key", value as AnyObject as! NSArray)
|
Where<NSManagedObject>("%K IN %@", "key", NSArray(array: value)),
|
||||||
XCTAssertEqual(whereClause1, whereClause2)
|
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject as! NSArray),
|
||||||
XCTAssertEqual(whereClause1, whereClause3)
|
Where<NSManagedObject>("key", isMemberOf: value)
|
||||||
XCTAssertEqual(whereClause1, whereClause4)
|
)
|
||||||
XCTAssertEqual(whereClause1, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause1, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause3)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause2, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause4)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause3, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause5)
|
|
||||||
XCTAssertEqual(whereClause4, whereClause6)
|
|
||||||
XCTAssertEqual(whereClause5, whereClause6)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
dynamic func test_ThatWhereClauseOperations_ComputeCorrectly() {
|
dynamic func test_ThatWhereClauseOperations_ComputeCorrectly() {
|
||||||
|
|
||||||
let whereClause1 = Where("key1", isEqualTo: "value1")
|
let whereClause1 = Where<NSManagedObject>("key1", isEqualTo: "value1")
|
||||||
let whereClause2 = Where("key2", isEqualTo: "value2")
|
let whereClause2 = Where<NSManagedObject>("key2", isEqualTo: "value2")
|
||||||
let whereClause3 = Where("key3", isEqualTo: "value3")
|
let whereClause3 = Where<NSManagedObject>("key3", isEqualTo: "value3")
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
@@ -325,6 +262,21 @@ final class WhereTests: XCTestCase {
|
|||||||
XCTAssertEqual(andWhere.predicate, andPredicate)
|
XCTAssertEqual(andWhere.predicate, andPredicate)
|
||||||
XCTAssertEqual(andWhere, whereClause1 && whereClause2 && whereClause3)
|
XCTAssertEqual(andWhere, whereClause1 && whereClause2 && whereClause3)
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
|
||||||
|
let andWhere = whereClause1 && whereClause2 && whereClause3
|
||||||
|
let noneWhere: Where<NSManagedObject>? = nil
|
||||||
|
let someWhere: Where<NSManagedObject>? = Where<NSManagedObject>("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 {
|
do {
|
||||||
|
|
||||||
let orWhere = whereClause1 || whereClause2 || whereClause3
|
let orWhere = whereClause1 || whereClause2 || whereClause3
|
||||||
@@ -341,12 +293,27 @@ final class WhereTests: XCTestCase {
|
|||||||
XCTAssertEqual(orWhere.predicate, orPredicate)
|
XCTAssertEqual(orWhere.predicate, orPredicate)
|
||||||
XCTAssertEqual(orWhere, whereClause1 || whereClause2 || whereClause3)
|
XCTAssertEqual(orWhere, whereClause1 || whereClause2 || whereClause3)
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
|
||||||
|
let orWhere = whereClause1 || whereClause2 || whereClause3
|
||||||
|
let noneWhere: Where<NSManagedObject>? = nil
|
||||||
|
let someWhere: Where<NSManagedObject>? = Where<NSManagedObject>("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
|
@objc
|
||||||
dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() {
|
dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() {
|
||||||
|
|
||||||
let whereClause = Where("key", isEqualTo: "value")
|
let whereClause = Where<NSManagedObject>("key", isEqualTo: "value")
|
||||||
let request = CoreStoreFetchRequest()
|
let request = CoreStoreFetchRequest()
|
||||||
whereClause.applyToFetchRequest(request)
|
whereClause.applyToFetchRequest(request)
|
||||||
XCTAssertNotNil(request.predicate)
|
XCTAssertNotNil(request.predicate)
|
||||||
|
|||||||
+136
-92
@@ -30,72 +30,77 @@ import CoreData
|
|||||||
// MARK: - AsynchronousDataTransaction
|
// MARK: - AsynchronousDataTransaction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The `AsynchronousDataTransaction` provides an interface for `NSManagedObject` creates, updates, and deletes. A transaction object should typically be only used from within a transaction block initiated from `DataStack.beginAsynchronous(_:)`, or from `CoreStore.beginAsynchronous(_:)`.
|
The `AsynchronousDataTransaction` provides an interface for `DynamicObject` creates, updates, and deletes. A transaction object should typically be only used from within a transaction block initiated from `DataStack.perform(asynchronous:...)`, or from `CoreStore.perform(synchronous:...)`.
|
||||||
*/
|
*/
|
||||||
public final class AsynchronousDataTransaction: BaseDataTransaction {
|
public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Saves the transaction changes. This method should not be used after the `commit()` method was already called once.
|
Cancels a transaction by throwing `CoreStoreError.userCancelled`.
|
||||||
|
```
|
||||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
|
try transaction.cancel()
|
||||||
|
```
|
||||||
|
- Important: Never use `try?` or `try!` on a `cancel()` call. Always use `try`. Using `try?` will swallow the cancellation and the transaction will proceed to commit as normal. Using `try!` will crash the app as `cancel()` will *always* throw an error.
|
||||||
*/
|
*/
|
||||||
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
|
public func cancel() throws -> Never {
|
||||||
|
|
||||||
CoreStore.assert(
|
throw CoreStoreError.userCancelled
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
|
||||||
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
|
||||||
)
|
|
||||||
CoreStore.assert(
|
|
||||||
!self.isCommitted,
|
|
||||||
"Attempted to commit a \(cs_typeName(self)) more than once."
|
|
||||||
)
|
|
||||||
|
|
||||||
self.isCommitted = true
|
|
||||||
let group = DispatchGroup()
|
|
||||||
group.enter()
|
|
||||||
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
|
|
||||||
|
|
||||||
self.result = result
|
|
||||||
completion(result)
|
|
||||||
group.leave()
|
|
||||||
}
|
|
||||||
group.wait()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Result
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Begins a child transaction synchronously where NSManagedObject creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once.
|
The `Result` contains the success or failure information for a completed transaction
|
||||||
|
|
||||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
|
||||||
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
|
||||||
*/
|
*/
|
||||||
@discardableResult
|
public enum Result<T> {
|
||||||
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
|
|
||||||
|
|
||||||
CoreStore.assert(
|
/**
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
`Result<T>.success` indicates that the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated `userInfo` is the value returned from the transaction closure.
|
||||||
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
|
*/
|
||||||
)
|
case success(userInfo: T)
|
||||||
CoreStore.assert(
|
|
||||||
!self.isCommitted,
|
|
||||||
"Attempted to begin a child transaction from an already committed \(cs_typeName(self))."
|
|
||||||
)
|
|
||||||
|
|
||||||
return SynchronousDataTransaction(
|
/**
|
||||||
mainContext: self.context,
|
`Result<T>.failure` indicates that the transaction either failed or was cancelled. The associated object for this value is a `CoreStoreError` enum value.
|
||||||
queue: self.childTransactionQueue,
|
*/
|
||||||
closure: closure).performAndWait()
|
case failure(error: CoreStoreError)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
|
||||||
|
*/
|
||||||
|
public var boolValue: Bool {
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
|
||||||
|
case .success: return true
|
||||||
|
case .failure: return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Internal
|
||||||
|
|
||||||
|
internal init(userInfo: T) {
|
||||||
|
|
||||||
|
self = .success(userInfo: userInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal init(error: CoreStoreError) {
|
||||||
|
|
||||||
|
self = .failure(error: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
// MARK: BaseDataTransaction
|
// MARK: BaseDataTransaction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a new `NSManagedObject` with the specified entity type.
|
Creates a new `NSManagedObject` or `CoreStoreObject` with the specified entity type.
|
||||||
|
|
||||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
|
||||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
|
||||||
*/
|
*/
|
||||||
public override func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
public override func create<D>(_ into: Into<D>) -> D {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
@@ -106,12 +111,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once.
|
Returns an editable proxy of a specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
|
|
||||||
- parameter object: the `NSManagedObject` type to be edited
|
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be edited
|
||||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
*/
|
*/
|
||||||
public override func edit<T: NSManagedObject>(_ object: T?) -> T? {
|
public override func edit<D: DynamicObject>(_ object: D?) -> D? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
@@ -122,13 +127,13 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `commit()` method was already called once.
|
Returns an editable proxy of the object with the specified `NSManagedObjectID`.
|
||||||
|
|
||||||
- parameter into: an `Into` clause specifying the entity type
|
- parameter into: an `Into` clause specifying the entity type
|
||||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
*/
|
*/
|
||||||
public override func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
public override func edit<D>(_ into: Into<D>, _ objectID: NSManagedObjectID) -> D? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
@@ -139,11 +144,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once.
|
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
|
|
||||||
- parameter object: the `NSManagedObject` type to be deleted
|
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
|
||||||
*/
|
*/
|
||||||
public override func delete(_ object: NSManagedObject?) {
|
public override func delete<D: DynamicObject>(_ object: D?) {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
@@ -154,13 +159,13 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes the specified `NSManagedObject`s.
|
Deletes the specified `DynamicObject`s.
|
||||||
|
|
||||||
- parameter object1: the `NSManagedObject` type to be deleted
|
- parameter object1: the `DynamicObject` to be deleted
|
||||||
- parameter object2: another `NSManagedObject` type to be deleted
|
- parameter object2: another `DynamicObject` to be deleted
|
||||||
- parameter objects: other `NSManagedObject`s type to be deleted
|
- parameter objects: other `DynamicObject`s to be deleted
|
||||||
*/
|
*/
|
||||||
public override func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
|
public override func delete<D: DynamicObject>(_ object1: D?, _ object2: D?, _ objects: D?...) {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
@@ -171,11 +176,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes the specified `NSManagedObject`s.
|
Deletes the specified `DynamicObject`s.
|
||||||
|
|
||||||
- parameter objects: the `NSManagedObject`s type to be deleted
|
- parameter objects: the `DynamicObject`s to be deleted
|
||||||
*/
|
*/
|
||||||
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
|
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
@@ -188,47 +193,86 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
|||||||
|
|
||||||
// MARK: Internal
|
// MARK: Internal
|
||||||
|
|
||||||
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
|
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue) {
|
||||||
|
|
||||||
self.closure = closure
|
|
||||||
|
|
||||||
super.init(mainContext: mainContext, queue: queue, supportsUndo: false, bypassesQueueing: false)
|
super.init(mainContext: mainContext, queue: queue, supportsUndo: false, bypassesQueueing: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func perform() {
|
internal func autoCommit(_ completion: @escaping (_ hasChanges: Bool, _ error: CoreStoreError?) -> Void) {
|
||||||
|
|
||||||
self.transactionQueue.async {
|
self.isCommitted = true
|
||||||
|
let group = DispatchGroup()
|
||||||
|
group.enter()
|
||||||
|
self.context.saveAsynchronouslyWithCompletion { (hasChanges, error) -> Void in
|
||||||
|
|
||||||
self.closure(self)
|
completion(hasChanges, error)
|
||||||
if !self.isCommitted && self.hasChanges {
|
self.result = (hasChanges, error)
|
||||||
|
group.leave()
|
||||||
|
}
|
||||||
|
group.wait()
|
||||||
|
self.context.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new auto-commiting methods `DataStack.perform(asynchronous:completion:)` or `DataStack.perform(asynchronous:success:failure:)`. Please read the documentation on the behavior of the new methods.")
|
||||||
|
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.isCommitted,
|
||||||
|
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||||
|
)
|
||||||
|
self.autoCommit { (hasChanges, error) in
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
|
||||||
|
completion(SaveResult(error))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
completion(SaveResult(hasChanges: hasChanges))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Secondary tasks spawned from AsynchronousDataTransactions and SynchronousDataTransactions are no longer supported. ")
|
||||||
|
@discardableResult
|
||||||
|
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.isCommitted,
|
||||||
|
"Attempted to begin a child transaction from an already committed \(cs_typeName(self))."
|
||||||
|
)
|
||||||
|
let childTransaction = SynchronousDataTransaction(
|
||||||
|
mainContext: self.context,
|
||||||
|
queue: self.childTransactionQueue
|
||||||
|
)
|
||||||
|
childTransaction.transactionQueue.cs_sync {
|
||||||
|
|
||||||
|
closure(childTransaction)
|
||||||
|
|
||||||
|
if !childTransaction.isCommitted && childTransaction.hasChanges {
|
||||||
|
|
||||||
CoreStore.log(
|
CoreStore.log(
|
||||||
.warning,
|
.warning,
|
||||||
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
|
message: "The closure for the \(cs_typeName(childTransaction)) completed without being committed. All changes made within the transaction were discarded."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
switch childTransaction.result {
|
||||||
|
|
||||||
internal func performAndWait() -> SaveResult? {
|
case .none: return nil
|
||||||
|
case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
|
||||||
self.transactionQueue.sync {
|
case .some(_, let error?): return SaveResult(error)
|
||||||
|
|
||||||
self.closure(self)
|
|
||||||
|
|
||||||
if !self.isCommitted && self.hasChanges {
|
|
||||||
|
|
||||||
CoreStore.log(
|
|
||||||
.warning,
|
|
||||||
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: Private
|
|
||||||
|
|
||||||
private let closure: (_ transaction: AsynchronousDataTransaction) -> Void
|
|
||||||
}
|
}
|
||||||
@@ -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: KeyPathString { 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 }
|
||||||
|
}
|
||||||
+28
-29
@@ -39,9 +39,9 @@ public extension BaseDataTransaction {
|
|||||||
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
||||||
- returns: the created `ImportableObject` instance, or `nil` if the import was ignored
|
- returns: the created `ImportableObject` instance, or `nil` if the import was ignored
|
||||||
*/
|
*/
|
||||||
public func importObject<T>(
|
public func importObject<D: ImportableObject>(
|
||||||
_ into: Into<T>,
|
_ into: Into<D>,
|
||||||
source: T.ImportSource) throws -> T? where T: NSManagedObject, T: ImportableObject {
|
source: D.ImportSource) throws -> D? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -50,8 +50,7 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
|
|
||||||
let entityType = into.entityClass as! T.Type
|
let entityType = into.entityClass
|
||||||
|
|
||||||
guard entityType.shouldInsert(from: source, in: self) else {
|
guard entityType.shouldInsert(from: source, in: self) else {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -70,9 +69,9 @@ public extension BaseDataTransaction {
|
|||||||
- parameter source: the object to import values from
|
- parameter source: the object to import values from
|
||||||
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
||||||
*/
|
*/
|
||||||
public func importObject<T>(
|
public func importObject<D: ImportableObject>(
|
||||||
_ object: T,
|
_ object: D,
|
||||||
source: T.ImportSource) throws where T: NSManagedObject, T: ImportableObject {
|
source: D.ImportSource) throws {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -98,9 +97,9 @@ public extension BaseDataTransaction {
|
|||||||
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
||||||
- returns: the array of created `ImportableObject` instances
|
- returns: the array of created `ImportableObject` instances
|
||||||
*/
|
*/
|
||||||
public func importObjects<T, S: Sequence>(
|
public func importObjects<D: ImportableObject, S: Sequence>(
|
||||||
_ into: Into<T>,
|
_ into: Into<D>,
|
||||||
sourceArray: S) throws -> [T] where T: NSManagedObject, T: ImportableObject, S.Iterator.Element == T.ImportSource {
|
sourceArray: S) throws -> [D] where S.Iterator.Element == D.ImportSource {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -109,9 +108,9 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
|
|
||||||
return try sourceArray.flatMap { (source) -> T? in
|
return try sourceArray.flatMap { (source) -> D? in
|
||||||
|
|
||||||
let entityType = into.entityClass as! T.Type
|
let entityType = into.entityClass
|
||||||
guard entityType.shouldInsert(from: source, in: self) else {
|
guard entityType.shouldInsert(from: source, in: self) else {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -134,9 +133,9 @@ public extension BaseDataTransaction {
|
|||||||
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
|
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
|
||||||
- returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
|
- returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
|
||||||
*/
|
*/
|
||||||
public func importUniqueObject<T>(
|
public func importUniqueObject<D: ImportableUniqueObject>(
|
||||||
_ into: Into<T>,
|
_ into: Into<D>,
|
||||||
source: T.ImportSource) throws -> T? where T: NSManagedObject, T: ImportableUniqueObject {
|
source: D.ImportSource) throws -> D? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -145,14 +144,14 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
|
|
||||||
let entityType = into.entityClass as! T.Type
|
let entityType = into.entityClass
|
||||||
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
|
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
|
||||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let object = self.fetchOne(From(entityType), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
if let object = self.fetchOne(From(entityType), Where<D>(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
||||||
|
|
||||||
guard entityType.shouldUpdate(from: source, in: self) else {
|
guard entityType.shouldUpdate(from: source, in: self) else {
|
||||||
|
|
||||||
@@ -178,7 +177,7 @@ public extension BaseDataTransaction {
|
|||||||
/**
|
/**
|
||||||
Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources.
|
Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources.
|
||||||
`ImportableUniqueObject` methods are called on the objects in the same order as they are in the `sourceArray`, and are returned in an array with that same order.
|
`ImportableUniqueObject` methods are called on the objects in the same order as they are in the `sourceArray`, and are returned in an array with that same order.
|
||||||
- Warning: If `sourceArray` contains multiple import sources with same ID, no merging will occur and ONLY THE LAST duplicate will be imported.
|
- Warning: If `sourceArray` contains multiple import sources with same ID, only the last `ImportSource` of the duplicates will be imported.
|
||||||
|
|
||||||
- parameter into: an `Into` clause specifying the entity type
|
- parameter into: an `Into` clause specifying the entity type
|
||||||
- parameter sourceArray: the array of objects to import values from
|
- parameter sourceArray: the array of objects to import values from
|
||||||
@@ -186,10 +185,10 @@ public extension BaseDataTransaction {
|
|||||||
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
|
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
|
||||||
- returns: the array of created/updated `ImportableUniqueObject` instances
|
- returns: the array of created/updated `ImportableUniqueObject` instances
|
||||||
*/
|
*/
|
||||||
public func importUniqueObjects<T, S: Sequence>(
|
public func importUniqueObjects<D: ImportableUniqueObject, S: Sequence>(
|
||||||
_ into: Into<T>,
|
_ into: Into<D>,
|
||||||
sourceArray: S,
|
sourceArray: S,
|
||||||
preProcess: @escaping (_ mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] where T: NSManagedObject, T: ImportableUniqueObject, S.Iterator.Element == T.ImportSource {
|
preProcess: @escaping (_ mapping: [D.UniqueIDType: D.ImportSource]) throws -> [D.UniqueIDType: D.ImportSource] = { $0 }) throws -> [D] where S.Iterator.Element == D.ImportSource {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -198,11 +197,11 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
|
|
||||||
let entityType = into.entityClass as! T.Type
|
let entityType = into.entityClass
|
||||||
var importSourceByID = Dictionary<T.UniqueIDType, T.ImportSource>()
|
var importSourceByID = Dictionary<D.UniqueIDType, D.ImportSource>()
|
||||||
let sortedIDs = try autoreleasepool {
|
let sortedIDs = try autoreleasepool {
|
||||||
|
|
||||||
return try sourceArray.flatMap { (source) -> T.UniqueIDType? in
|
return try sourceArray.flatMap { (source) -> D.UniqueIDType? in
|
||||||
|
|
||||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||||
|
|
||||||
@@ -215,12 +214,12 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
|
importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
|
||||||
|
|
||||||
var existingObjectsByID = Dictionary<T.UniqueIDType, T>()
|
var existingObjectsByID = Dictionary<D.UniqueIDType, D>()
|
||||||
self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
|
self.fetchAll(From(entityType), Where<D>(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
|
||||||
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
|
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
|
||||||
|
|
||||||
var processedObjectIDs = Set<T.UniqueIDType>()
|
var processedObjectIDs = Set<D.UniqueIDType>()
|
||||||
var result = [T]()
|
var result = [D]()
|
||||||
|
|
||||||
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
|
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
|
||||||
|
|
||||||
@@ -0,0 +1,552 @@
|
|||||||
|
//
|
||||||
|
// BaseDataTransaction+Querying.swift
|
||||||
|
// CoreStore
|
||||||
|
//
|
||||||
|
// Copyright © 2015 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: - DataTransaction
|
||||||
|
|
||||||
|
extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes all `DynamicObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
- returns: the number of `DynamicObject`s deleted
|
||||||
|
*/
|
||||||
|
@discardableResult
|
||||||
|
public func deleteAll<D>(_ from: From<D>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.deleteAll(from, deleteClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes all `DynamicObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
- returns: the number of `DynamicObject`s deleted
|
||||||
|
*/
|
||||||
|
@discardableResult
|
||||||
|
public func deleteAll<D>(_ from: From<D>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.deleteAll(from, deleteClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes all `DynamicObject`s that satisfy the specified conditions.
|
||||||
|
```
|
||||||
|
transaction.deleteAll(From<Person>().where(\.age > 50))
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` clause chain created from a `From` clause
|
||||||
|
- returns: the number of `DynamicObject`s deleted
|
||||||
|
*/
|
||||||
|
@discardableResult
|
||||||
|
public func deleteAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.context.deleteAll(clauseChain.from, clauseChain.fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FetchableSource
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `DynamicObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
|
||||||
|
|
||||||
|
- parameter object: a reference to the object created/fetched outside the transaction
|
||||||
|
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||||
|
*/
|
||||||
|
public func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
|
||||||
|
|
||||||
|
return self.context.fetchExisting(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `DynamicObject` instance in the transaction's context from an `NSManagedObjectID`.
|
||||||
|
|
||||||
|
- parameter objectID: the `NSManagedObjectID` for the object
|
||||||
|
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||||
|
*/
|
||||||
|
public func fetchExisting<D: DynamicObject>(_ objectID: NSManagedObjectID) -> D? {
|
||||||
|
|
||||||
|
return self.context.fetchExisting(objectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `DynamicObject` instances in the transaction's context from references created from a transaction or from a different managed object context.
|
||||||
|
|
||||||
|
- parameter objects: an array of `DynamicObject`s created/fetched outside the transaction
|
||||||
|
- returns: the `DynamicObject` array for objects that exists in the transaction
|
||||||
|
*/
|
||||||
|
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objects: S) -> [D] where S.Iterator.Element == D {
|
||||||
|
|
||||||
|
return self.context.fetchExisting(objects)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `DynamicObject` instances in the transaction's context from a list of `NSManagedObjectID`.
|
||||||
|
|
||||||
|
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||||
|
- returns: the `DynamicObject` array for objects that exists in the transaction
|
||||||
|
*/
|
||||||
|
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objectIDs: S) -> [D] where S.Iterator.Element == NSManagedObjectID {
|
||||||
|
|
||||||
|
return self.context.fetchExisting(objectIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> D? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchOne(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> D? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchOne(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let youngestTeen = transaction.fetchOne(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) -> B.ObjectType? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchOne(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [D]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchAll(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [D]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchAll(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let people = transaction.fetchAll(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> [B.ObjectType]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchAll(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> Int? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchCount(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchCount(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let numberOfAdults = transaction.fetchCount(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchCount(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchObjectID(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchObjectID(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let youngestTeenID = transaction.fetchObjectID(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) -> NSManagedObjectID? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchObjectID(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchObjectIDs(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchObjectIDs(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let idsOfAdults = transaction.fetchObjectIDs(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) -> [NSManagedObjectID]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.fetchObjectIDs(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: QueryableSource
|
||||||
|
|
||||||
|
/**
|
||||||
|
Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) -> U? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.queryValue(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Queries aggregate values or aggregates as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) -> U? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.queryValue(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
```
|
||||||
|
let averageAdultAge = transaction.queryValue(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.select(Int.self, .average(\.age))
|
||||||
|
.where(\.age > 18)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request.
|
||||||
|
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.queryAttributes(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.queryAttributes(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
```
|
||||||
|
let results = dataStack.queryAttributes(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.select(
|
||||||
|
NSDictionary.self,
|
||||||
|
.attribute(\.age, as: "age"),
|
||||||
|
.count(\.age, as: "numberOfPeople")
|
||||||
|
)
|
||||||
|
.groupBy(\.age)
|
||||||
|
)
|
||||||
|
for dictionary in results! {
|
||||||
|
let age = dictionary["age"] as! Int
|
||||||
|
let count = dictionary["numberOfPeople"] as! Int
|
||||||
|
print("There are \(count) people who are \(age) years old."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request.
|
||||||
|
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.isRunningInAllowedQueue(),
|
||||||
|
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
return self.context.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FetchableSource, QueryableSource
|
||||||
|
|
||||||
|
/**
|
||||||
|
The internal `NSManagedObjectContext` managed by this instance. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
|
||||||
|
*/
|
||||||
|
public func unsafeContext() -> NSManagedObjectContext {
|
||||||
|
|
||||||
|
return self.context
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Obsoleted
|
||||||
|
|
||||||
|
@available(*, obsoleted: 3.1, renamed: "unsafeContext()")
|
||||||
|
public func internalContext() -> NSManagedObjectContext {
|
||||||
|
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
}
|
||||||
+138
-136
@@ -45,32 +45,36 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a new `NSManagedObject` with the specified entity type.
|
Creates a new `NSManagedObject` or `CoreStoreObject` with the specified entity type.
|
||||||
|
|
||||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
|
||||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
|
||||||
*/
|
*/
|
||||||
public func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
public func create<D>(_ into: Into<D>) -> D {
|
||||||
|
|
||||||
let entityClass = (into.entityClass as! T.Type)
|
let entityClass = into.entityClass
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
|
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
|
||||||
)
|
)
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
|
let dataStack = context.parentStack!
|
||||||
|
let entityIdentifier = EntityIdentifier(entityClass)
|
||||||
if into.inferStoreIfPossible {
|
if into.inferStoreIfPossible {
|
||||||
|
|
||||||
switch context.parentStack!.persistentStoreForEntityClass(
|
switch dataStack.persistentStore(
|
||||||
entityClass,
|
for: entityIdentifier,
|
||||||
configuration: nil,
|
configuration: nil,
|
||||||
inferStoreIfPossible: true
|
inferStoreIfPossible: true
|
||||||
) {
|
) {
|
||||||
|
|
||||||
case (let persistentStore?, _):
|
case (let persistentStore?, _):
|
||||||
let object = entityClass.createInContext(context)
|
return entityClass.cs_forceCreate(
|
||||||
context.assign(object, to: persistentStore)
|
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
|
||||||
return object
|
into: context,
|
||||||
|
assignTo: persistentStore
|
||||||
|
)
|
||||||
|
|
||||||
case (nil, true):
|
case (nil, true):
|
||||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||||
@@ -81,17 +85,19 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
switch context.parentStack!.persistentStoreForEntityClass(
|
switch dataStack.persistentStore(
|
||||||
entityClass,
|
for: entityIdentifier,
|
||||||
configuration: into.configuration
|
configuration: into.configuration
|
||||||
?? type(of: into).defaultConfigurationName,
|
?? DataStack.defaultConfigurationName,
|
||||||
inferStoreIfPossible: false
|
inferStoreIfPossible: false
|
||||||
) {
|
) {
|
||||||
|
|
||||||
case (let persistentStore?, _):
|
case (let persistentStore?, _):
|
||||||
let object = entityClass.createInContext(context)
|
return entityClass.cs_forceCreate(
|
||||||
context.assign(object, to: persistentStore)
|
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
|
||||||
return object
|
into: context,
|
||||||
|
assignTo: persistentStore
|
||||||
|
)
|
||||||
|
|
||||||
case (nil, true):
|
case (nil, true):
|
||||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||||
@@ -110,12 +116,12 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an editable proxy of a specified `NSManagedObject`.
|
Returns an editable proxy of a specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
|
|
||||||
- parameter object: the `NSManagedObject` type to be edited
|
- parameter object: the `NSManagedObject` or `CoreStoreObject` type to be edited
|
||||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
*/
|
*/
|
||||||
public func edit<T: NSManagedObject>(_ object: T?) -> T? {
|
public func edit<D: DynamicObject>(_ object: D?) -> D? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -133,9 +139,9 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
|
|
||||||
- parameter into: an `Into` clause specifying the entity type
|
- parameter into: an `Into` clause specifying the entity type
|
||||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
*/
|
*/
|
||||||
public func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
public func edit<D>(_ into: Into<D>, _ objectID: NSManagedObjectID) -> D? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
@@ -143,56 +149,54 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
)
|
)
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
into.inferStoreIfPossible
|
into.inferStoreIfPossible
|
||||||
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
|
|| (into.configuration ?? DataStack.defaultConfigurationName) == objectID.persistentStore?.configurationName,
|
||||||
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
|
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
|
||||||
)
|
)
|
||||||
return self.fetchExisting(objectID) as? T
|
return self.fetchExisting(objectID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes a specified `NSManagedObject`.
|
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
|
||||||
|
|
||||||
- parameter object: the `NSManagedObject` to be deleted
|
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
|
||||||
*/
|
*/
|
||||||
public func delete(_ object: NSManagedObject?) {
|
public func delete<D: DynamicObject>(_ object: D?) {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
"Attempted to delete an entity outside its designated queue."
|
"Attempted to delete an entity outside its designated queue."
|
||||||
)
|
)
|
||||||
guard let object = object else {
|
let context = self.context
|
||||||
|
object
|
||||||
return
|
.flatMap(context.fetchExisting)
|
||||||
}
|
.flatMap({ context.delete($0.cs_toRaw()) })
|
||||||
self.context.fetchExisting(object)?.deleteFromContext()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes the specified `NSManagedObject`s.
|
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s.
|
||||||
|
|
||||||
- parameter object1: the `NSManagedObject` to be deleted
|
- parameter object1: the `NSManagedObject` or `CoreStoreObject` to be deleted
|
||||||
- parameter object2: another `NSManagedObject` to be deleted
|
- parameter object2: another `NSManagedObject` or `CoreStoreObject` to be deleted
|
||||||
- parameter objects: other `NSManagedObject`s to be deleted
|
- parameter objects: other `NSManagedObject`s or `CoreStoreObject`s to be deleted
|
||||||
*/
|
*/
|
||||||
public func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
|
public func delete<D: DynamicObject>(_ object1: D?, _ object2: D?, _ objects: D?...) {
|
||||||
|
|
||||||
self.delete(([object1, object2] + objects).flatMap { $0 })
|
self.delete(([object1, object2] + objects).flatMap { $0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes the specified `NSManagedObject`s.
|
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s.
|
||||||
|
|
||||||
- parameter objects: the `NSManagedObject`s to be deleted
|
- parameter objects: the `NSManagedObject`s or `CoreStoreObject`s to be deleted
|
||||||
*/
|
*/
|
||||||
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
|
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
"Attempted to delete entities outside their designated queue."
|
"Attempted to delete entities outside their designated queue."
|
||||||
)
|
)
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
objects.forEach { context.fetchExisting($0)?.deleteFromContext() }
|
objects.forEach { context.fetchExisting($0).flatMap({ context.delete($0.cs_toRaw()) }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,7 +208,6 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
self.isRunningInAllowedQueue(),
|
self.isRunningInAllowedQueue(),
|
||||||
"Attempted to refresh entities outside their designated queue."
|
"Attempted to refresh entities outside their designated queue."
|
||||||
)
|
)
|
||||||
|
|
||||||
self.context.refreshAndMergeAllObjects()
|
self.context.refreshAndMergeAllObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,11 +215,12 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
// MARK: Inspecting Pending Objects
|
// MARK: Inspecting Pending Objects
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `DynamicObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- returns: a `Set` of pending `NSManagedObject`s that were inserted to the transaction.
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
|
- returns: a `Set` of pending `DynamicObject`s of the specified type that were inserted to the transaction.
|
||||||
*/
|
*/
|
||||||
public func insertedObjects() -> Set<NSManagedObject> {
|
public func insertedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
@@ -226,28 +230,7 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
|
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
|
||||||
return self.context.insertedObjects
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
|
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
|
||||||
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
|
|
||||||
*/
|
|
||||||
public func insertedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
|
|
||||||
|
|
||||||
CoreStore.assert(
|
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
|
||||||
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
|
|
||||||
)
|
|
||||||
CoreStore.assert(
|
|
||||||
!self.isCommitted,
|
|
||||||
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
|
|
||||||
)
|
|
||||||
|
|
||||||
return Set(self.context.insertedObjects.flatMap { $0 as? T })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,17 +248,16 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
|
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
|
||||||
return Set(self.context.insertedObjects.map { $0.objectID })
|
return Set(self.context.insertedObjects.map { $0.objectID })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
|
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
|
||||||
*/
|
*/
|
||||||
public func insertedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
|
public func insertedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
@@ -285,16 +267,16 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
|
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
|
||||||
return Set(self.context.insertedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `DynamicObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- returns: a `Set` of pending `NSManagedObject`s that were updated to the transaction.
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
|
- returns: a `Set` of pending `DynamicObject`s of the specified type that were updated in the transaction.
|
||||||
*/
|
*/
|
||||||
public func updatedObjects() -> Set<NSManagedObject> {
|
public func updatedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
@@ -304,28 +286,7 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
|
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
|
||||||
return self.context.updatedObjects
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
|
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
|
||||||
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
|
|
||||||
*/
|
|
||||||
public func updatedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
|
|
||||||
|
|
||||||
CoreStore.assert(
|
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
|
||||||
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
|
|
||||||
)
|
|
||||||
CoreStore.assert(
|
|
||||||
!self.isCommitted,
|
|
||||||
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
|
|
||||||
)
|
|
||||||
|
|
||||||
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,17 +304,16 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
|
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
|
||||||
return Set(self.context.updatedObjects.map { $0.objectID })
|
return Set(self.context.updatedObjects.map { $0.objectID })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
|
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
|
||||||
*/
|
*/
|
||||||
public func updatedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
|
public func updatedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
@@ -363,16 +323,16 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
|
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
|
||||||
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `DynamicObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- returns: a `Set` of pending `NSManagedObject`s that were deleted from the transaction.
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
|
- returns: a `Set` of pending `DynamicObject`s of the specified type that were deleted from the transaction.
|
||||||
*/
|
*/
|
||||||
public func deletedObjects() -> Set<NSManagedObject> {
|
public func deletedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
@@ -382,34 +342,13 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
|
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
|
||||||
return self.context.deletedObjects
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
|
||||||
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
|
|
||||||
*/
|
|
||||||
public func deletedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
|
|
||||||
|
|
||||||
CoreStore.assert(
|
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
|
||||||
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
|
|
||||||
)
|
|
||||||
CoreStore.assert(
|
|
||||||
!self.isCommitted,
|
|
||||||
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
|
|
||||||
)
|
|
||||||
|
|
||||||
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
||||||
*/
|
*/
|
||||||
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
|
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
|
||||||
@@ -422,17 +361,16 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
|
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
|
||||||
return Set(self.context.deletedObjects.map { $0.objectID })
|
return Set(self.context.deletedObjects.map { $0.objectID })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
- parameter entity: the `DynamicObject` subclass to filter
|
||||||
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
||||||
*/
|
*/
|
||||||
public func deletedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
|
public func deletedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
@@ -442,20 +380,34 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
!self.isCommitted,
|
!self.isCommitted,
|
||||||
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
|
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
|
||||||
)
|
)
|
||||||
|
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
|
||||||
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: 3rd Party Utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
|
||||||
|
```
|
||||||
|
enum Static {
|
||||||
|
static var myDataKey: Void?
|
||||||
|
}
|
||||||
|
transaction.userInfo[&Static.myDataKey] = myObject
|
||||||
|
```
|
||||||
|
- Important: Do not use this method to store thread-sensitive data.
|
||||||
|
*/
|
||||||
|
public let userInfo = UserInfo()
|
||||||
|
|
||||||
|
|
||||||
// MARK: Internal
|
// MARK: Internal
|
||||||
|
|
||||||
internal let context: NSManagedObjectContext
|
internal let context: NSManagedObjectContext
|
||||||
internal let transactionQueue: DispatchQueue
|
internal let transactionQueue: DispatchQueue
|
||||||
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childtransactionqueue")
|
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childTransactionQueue")
|
||||||
internal let supportsUndo: Bool
|
internal let supportsUndo: Bool
|
||||||
internal let bypassesQueueing: Bool
|
internal let bypassesQueueing: Bool
|
||||||
internal var isCommitted = false
|
internal var isCommitted = false
|
||||||
internal var result: SaveResult?
|
internal var result: (hasChanges: Bool, error: CoreStoreError?)?
|
||||||
|
|
||||||
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
|
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
|
||||||
|
|
||||||
@@ -485,4 +437,54 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
|
|
||||||
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
|
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
|
||||||
|
self.context.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use insertedObjects(_:) and pass the specific entity type")
|
||||||
|
public func insertedObjects() -> Set<NSManagedObject> {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.isCommitted,
|
||||||
|
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
|
||||||
|
)
|
||||||
|
return self.context.insertedObjects
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use updatedObjects(_:) and pass the specific entity type")
|
||||||
|
public func updatedObjects() -> Set<NSManagedObject> {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.isCommitted,
|
||||||
|
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
|
||||||
|
)
|
||||||
|
return self.context.updatedObjects
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use deletedObjects(_:) and pass the specific entity type")
|
||||||
|
public func deletedObjects() -> Set<NSManagedObject> {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.isCommitted,
|
||||||
|
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
|
||||||
|
)
|
||||||
|
return self.context.deletedObjects
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+57
-25
@@ -35,37 +35,34 @@ import CoreData
|
|||||||
- SeeAlso: `AsynchronousDataTransaction`
|
- SeeAlso: `AsynchronousDataTransaction`
|
||||||
*/
|
*/
|
||||||
@objc
|
@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.
|
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
||||||
|
|
||||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
|
- parameter success: the block executed if the save succeeds.
|
||||||
|
- parameter failure: the block executed if the save fails. A `CSError` is reported as the argument of the block.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
|
||||||
|
|
||||||
self.bridgeToSwift.commit { (result) in
|
CoreStore.assert(
|
||||||
|
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.bridgeToSwift.isCommitted,
|
||||||
|
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||||
|
)
|
||||||
|
self.bridgeToSwift.autoCommit { (_, error) in
|
||||||
|
|
||||||
completion?(result.bridgeToObjectiveC)
|
if let error = error {
|
||||||
}
|
|
||||||
|
failure?(error.bridgeToObjectiveC)
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
/**
|
success?()
|
||||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
|
||||||
|
|
||||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
|
||||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
@discardableResult
|
|
||||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
|
||||||
|
|
||||||
return bridge {
|
|
||||||
|
|
||||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
closure(transaction.bridgeToObjectiveC)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,9 +142,9 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
|||||||
|
|
||||||
public typealias SwiftType = AsynchronousDataTransaction
|
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) {
|
public required init(_ swiftValue: AsynchronousDataTransaction) {
|
||||||
@@ -155,9 +152,44 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
|||||||
super.init(swiftValue as BaseDataTransaction)
|
super.init(swiftValue as BaseDataTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public required init(_ swiftValue: BaseDataTransaction) {
|
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||||
|
|
||||||
super.init(swiftValue as! AsynchronousDataTransaction)
|
super.init(swiftValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -[CSAsynchronousDataTransaction commitWithSuccess:failure:] method.")
|
||||||
|
@objc
|
||||||
|
public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
|
||||||
|
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||||
|
)
|
||||||
|
CoreStore.assert(
|
||||||
|
!self.bridgeToSwift.isCommitted,
|
||||||
|
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||||
|
)
|
||||||
|
self.bridgeToSwift.commit { (result) in
|
||||||
|
|
||||||
|
completion?(result.bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Secondary tasks spawned from CSAsynchronousDataTransactions and CSSynchronousDataTransactions are no longer supported. ")
|
||||||
|
@objc
|
||||||
|
@discardableResult
|
||||||
|
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||||
|
|
||||||
|
return bridge {
|
||||||
|
|
||||||
|
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||||
|
|
||||||
|
closure(transaction.bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+16
-16
@@ -40,7 +40,7 @@ public extension CSBaseDataTransaction {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
||||||
|
|
||||||
return self.bridgeToSwift.context.fetchExisting(object)
|
return self.swiftTransaction.context.fetchExisting(object) as NSManagedObject?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +52,7 @@ public extension CSBaseDataTransaction {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
||||||
|
|
||||||
return self.bridgeToSwift.context.fetchExisting(objectID)
|
return self.swiftTransaction.context.fetchExisting(objectID) as NSManagedObject?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +64,7 @@ public extension CSBaseDataTransaction {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
||||||
|
|
||||||
return self.bridgeToSwift.context.fetchExisting(objects)
|
return self.swiftTransaction.context.fetchExisting(objects) as [NSManagedObject]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +76,7 @@ public extension CSBaseDataTransaction {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
||||||
|
|
||||||
return self.bridgeToSwift.context.fetchExisting(objectIDs)
|
return self.swiftTransaction.context.fetchExisting(objectIDs) as [NSManagedObject]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,10 +90,10 @@ public extension CSBaseDataTransaction {
|
|||||||
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
|
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
"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]? {
|
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
"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? {
|
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
||||||
)
|
)
|
||||||
return self.bridgeToSwift.context
|
return self.swiftTransaction.context
|
||||||
.fetchCount(from, fetchClauses)
|
.fetchCount(from, fetchClauses)
|
||||||
.flatMap { NSNumber(value: $0) }
|
.flatMap { NSNumber(value: $0) }
|
||||||
}
|
}
|
||||||
@@ -143,10 +143,10 @@ public extension CSBaseDataTransaction {
|
|||||||
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
|
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||||
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
|
"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? {
|
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||||
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
"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]]? {
|
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bridgeToSwift.isRunningInAllowedQueue(),
|
self.swiftTransaction.isRunningInAllowedQueue(),
|
||||||
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
|
"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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+41
-59
@@ -35,7 +35,7 @@ import CoreData
|
|||||||
- SeeAlso: `BaseDataTransaction`
|
- SeeAlso: `BaseDataTransaction`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
public class CSBaseDataTransaction: NSObject {
|
||||||
|
|
||||||
// MARK: Object management
|
// MARK: Object management
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public var hasChanges: Bool {
|
public var hasChanges: Bool {
|
||||||
|
|
||||||
return self.bridgeToSwift.hasChanges
|
return self.swiftTransaction.hasChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +57,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func createInto(_ into: CSInto) -> Any {
|
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
|
@objc
|
||||||
public func editObject(_ object: NSManagedObject?) -> Any? {
|
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
|
@objc
|
||||||
public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
|
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
|
@objc
|
||||||
public func deleteObject(_ object: NSManagedObject?) {
|
public func deleteObject(_ object: NSManagedObject?) {
|
||||||
|
|
||||||
self.bridgeToSwift.delete(object)
|
self.swiftTransaction.delete(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +104,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func deleteObjects(_ objects: [NSManagedObject]) {
|
public func deleteObjects(_ objects: [NSManagedObject]) {
|
||||||
|
|
||||||
self.bridgeToSwift.delete(objects)
|
self.swiftTransaction.delete(objects)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,23 +113,12 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func refreshAndMergeAllObjects() {
|
public func refreshAndMergeAllObjects() {
|
||||||
|
|
||||||
self.bridgeToSwift.refreshAndMergeAllObjects()
|
self.swiftTransaction.refreshAndMergeAllObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: Inspecting Pending Objects
|
// MARK: Inspecting Pending Objects
|
||||||
|
|
||||||
/**
|
|
||||||
Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
|
|
||||||
|
|
||||||
- returns: an `NSSet` of pending `NSManagedObject`s that were inserted to the transaction.
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public func insertedObjects() -> Set<NSManagedObject> {
|
|
||||||
|
|
||||||
return self.bridgeToSwift.insertedObjects()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
|
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
|
||||||
|
|
||||||
@@ -139,7 +128,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||||
|
|
||||||
return self.bridgeToSwift.insertedObjects(entity)
|
return self.swiftTransaction.insertedObjects(entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,7 +139,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
|
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
return self.bridgeToSwift.insertedObjectIDs()
|
return self.swiftTransaction.insertedObjectIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,18 +151,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
return self.bridgeToSwift.insertedObjectIDs(entity)
|
return self.swiftTransaction.insertedObjectIDs(entity)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `-commit*:` method was called.
|
|
||||||
|
|
||||||
- returns: an `NSSet` of pending `NSManagedObject`s that were updated to the transaction.
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public func updatedObjects() -> Set<NSManagedObject> {
|
|
||||||
|
|
||||||
return self.bridgeToSwift.updatedObjects()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +163,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||||
|
|
||||||
return self.bridgeToSwift.updatedObjects(entity)
|
return self.swiftTransaction.updatedObjects(entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,7 +174,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
|
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
return self.bridgeToSwift.updatedObjectIDs()
|
return self.swiftTransaction.updatedObjectIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,18 +186,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
return self.bridgeToSwift.updatedObjectIDs(entity)
|
return self.swiftTransaction.updatedObjectIDs(entity)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
|
|
||||||
|
|
||||||
- returns: an `NSSet` of pending `NSManagedObject`s that were deleted from the transaction.
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public func deletedObjects() -> Set<NSManagedObject> {
|
|
||||||
|
|
||||||
return self.bridgeToSwift.deletedObjects()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,19 +198,18 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
|
||||||
|
|
||||||
return self.bridgeToSwift.deletedObjects(entity)
|
return self.swiftTransaction.deletedObjects(entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
|
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
|
||||||
|
|
||||||
- parameter entity: the `NSManagedObject` subclass to filter
|
|
||||||
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
|
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
return self.bridgeToSwift.deletedObjectIDs()
|
return self.swiftTransaction.deletedObjectIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,7 +221,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
@objc
|
@objc
|
||||||
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
|
||||||
|
|
||||||
return self.bridgeToSwift.deletedObjectIDs(entity)
|
return self.swiftTransaction.deletedObjectIDs(entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -263,7 +229,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
public override var hash: Int {
|
public override var hash: Int {
|
||||||
|
|
||||||
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
return ObjectIdentifier(self.swiftTransaction).hashValue
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func isEqual(_ object: Any?) -> Bool {
|
public override func isEqual(_ object: Any?) -> Bool {
|
||||||
@@ -272,25 +238,41 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
return false
|
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
|
self.swiftTransaction = swiftValue
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
public var bridgeToSwift: BaseDataTransaction {
|
|
||||||
|
|
||||||
return self.swiftTransaction
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use -[insertedObjectsOfType:] and pass the specific entity class")
|
||||||
|
@objc
|
||||||
|
public func insertedObjects() -> Set<NSManagedObject> {
|
||||||
|
|
||||||
|
return self.swiftTransaction.insertedObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use -[updatedObjectsOfType:] and pass the specific entity class")
|
||||||
|
@objc
|
||||||
|
public func updatedObjects() -> Set<NSManagedObject> {
|
||||||
|
|
||||||
// MARK: Private
|
return self.swiftTransaction.updatedObjects()
|
||||||
|
}
|
||||||
|
|
||||||
private let swiftTransaction: BaseDataTransaction
|
@available(*, deprecated, message: "Use -[deletedObjectsOfType:] and pass the specific entity class")
|
||||||
|
@objc
|
||||||
|
public func deletedObjects() -> Set<NSManagedObject> {
|
||||||
|
|
||||||
|
return self.swiftTransaction.deletedObjects()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-4
@@ -27,10 +27,9 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSCoreStore
|
// MARK: - CSCoreStore
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
public extension CSCoreStore {
|
public extension CSCoreStore {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,5 +111,3 @@ public extension CSCoreStore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -44,21 +44,9 @@ public extension CSCoreStore {
|
|||||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static var entityClassesByName: [String: NSManagedObject.Type] {
|
public static func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||||
|
|
||||||
return CoreStore.entityTypesByName
|
return CoreStore.entityTypesByName(for: type)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the entity class for the given entity name from the `defaultStack`'s model.
|
|
||||||
|
|
||||||
- parameter name: the entity name
|
|
||||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public static func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
|
|
||||||
|
|
||||||
return CoreStore.entityTypesByName[name]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,4 +125,21 @@ public extension CSCoreStore {
|
|||||||
|
|
||||||
return self.defaultStack.addSQLiteStorageAndWait(storage, error: error)
|
return self.defaultStack.addSQLiteStorageAndWait(storage, error: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||||
|
@objc
|
||||||
|
public static var entityClassesByName: [EntityName: NSManagedObject.Type] {
|
||||||
|
|
||||||
|
return CoreStore.entityTypesByName
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||||
|
@objc
|
||||||
|
public static func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
|
||||||
|
|
||||||
|
return CoreStore.entityTypesByName[name]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+14
-13
@@ -38,10 +38,7 @@ public extension CSCoreStore {
|
|||||||
@objc
|
@objc
|
||||||
public static func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
|
public static func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
|
||||||
|
|
||||||
return CoreStore.beginAsynchronous { (transaction) in
|
self.defaultStack.beginAsynchronous(closure)
|
||||||
|
|
||||||
closure(transaction.bridgeToObjectiveC)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,16 +48,9 @@ public extension CSCoreStore {
|
|||||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
@discardableResult
|
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
|
||||||
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
|
||||||
|
|
||||||
return bridge {
|
return self.defaultStack.beginSynchronous(closure, error: error)
|
||||||
|
|
||||||
CoreStore.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
closure(transaction.bridgeToObjectiveC)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,4 +91,15 @@ public extension CSCoreStore {
|
|||||||
|
|
||||||
CoreStore.refreshAndMergeAllObjects()
|
CoreStore.refreshAndMergeAllObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new +[CSCoreStore beginSynchronous:error:] API that reports failure using an error instance.")
|
||||||
|
@objc
|
||||||
|
@discardableResult
|
||||||
|
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||||
|
|
||||||
|
return self.defaultStack.beginSynchronous(closure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
-18
@@ -27,10 +27,9 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSDataStack
|
// MARK: - CSDataStack
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
public extension CSDataStack {
|
public extension CSDataStack {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,10 +41,7 @@ public extension CSDataStack {
|
|||||||
@objc
|
@objc
|
||||||
public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
|
public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
|
||||||
|
|
||||||
return bridge {
|
return self.bridgeToSwift.monitorObject(object).bridgeToObjectiveC
|
||||||
|
|
||||||
self.bridgeToSwift.monitorObject(object)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,9 +62,7 @@ public extension CSDataStack {
|
|||||||
fetchClauses.contains { $0 is CSOrderBy },
|
fetchClauses.contains { $0 is CSOrderBy },
|
||||||
"A CSListMonitor requires a CSOrderBy clause."
|
"A CSListMonitor requires a CSOrderBy clause."
|
||||||
)
|
)
|
||||||
return bridge {
|
return ListMonitor(
|
||||||
|
|
||||||
ListMonitor(
|
|
||||||
dataStack: self.bridgeToSwift,
|
dataStack: self.bridgeToSwift,
|
||||||
from: from.bridgeToSwift,
|
from: from.bridgeToSwift,
|
||||||
sectionBy: nil,
|
sectionBy: nil,
|
||||||
@@ -76,8 +70,7 @@ public extension CSDataStack {
|
|||||||
|
|
||||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||||
}
|
}
|
||||||
)
|
).bridgeToObjectiveC
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,9 +125,7 @@ public extension CSDataStack {
|
|||||||
fetchClauses.contains { $0 is CSOrderBy },
|
fetchClauses.contains { $0 is CSOrderBy },
|
||||||
"A CSListMonitor requires an CSOrderBy clause."
|
"A CSListMonitor requires an CSOrderBy clause."
|
||||||
)
|
)
|
||||||
return bridge {
|
return ListMonitor(
|
||||||
|
|
||||||
ListMonitor(
|
|
||||||
dataStack: self.bridgeToSwift,
|
dataStack: self.bridgeToSwift,
|
||||||
from: from.bridgeToSwift,
|
from: from.bridgeToSwift,
|
||||||
sectionBy: sectionBy.bridgeToSwift,
|
sectionBy: sectionBy.bridgeToSwift,
|
||||||
@@ -142,8 +133,7 @@ public extension CSDataStack {
|
|||||||
|
|
||||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||||
}
|
}
|
||||||
)
|
).bridgeToObjectiveC
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,5 +169,3 @@ public extension CSDataStack {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -40,7 +40,7 @@ public extension CSDataStack {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
||||||
|
|
||||||
return self.bridgeToSwift.mainContext.fetchExisting(object)
|
return self.bridgeToSwift.mainContext.fetchExisting(object) as NSManagedObject?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +52,7 @@ public extension CSDataStack {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
||||||
|
|
||||||
return self.bridgeToSwift.mainContext.fetchExisting(objectID)
|
return self.bridgeToSwift.mainContext.fetchExisting(objectID) as NSManagedObject?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +64,7 @@ public extension CSDataStack {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
||||||
|
|
||||||
return self.bridgeToSwift.mainContext.fetchExisting(objects)
|
return self.bridgeToSwift.mainContext.fetchExisting(objects) as [NSManagedObject]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +76,7 @@ public extension CSDataStack {
|
|||||||
@objc
|
@objc
|
||||||
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
||||||
|
|
||||||
return self.bridgeToSwift.mainContext.fetchExisting(objectIDs)
|
return self.bridgeToSwift.mainContext.fetchExisting(objectIDs) as [NSManagedObject]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+55
-8
@@ -38,27 +38,57 @@ public extension CSDataStack {
|
|||||||
@objc
|
@objc
|
||||||
public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
|
public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
|
||||||
|
|
||||||
return self.bridgeToSwift.beginAsynchronous { (transaction) in
|
self.bridgeToSwift.perform(
|
||||||
|
asynchronous: { (transaction) in
|
||||||
|
|
||||||
closure(transaction.bridgeToObjectiveC)
|
let csTransaction = transaction.bridgeToObjectiveC
|
||||||
|
closure(csTransaction)
|
||||||
|
if !transaction.isCommitted && transaction.hasChanges {
|
||||||
|
|
||||||
|
CoreStore.log(
|
||||||
|
.warning,
|
||||||
|
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
try transaction.cancel()
|
||||||
|
},
|
||||||
|
completion: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
||||||
|
|
||||||
- parameter closure: the block 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 closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
|
||||||
|
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
@discardableResult
|
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
|
||||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
|
||||||
|
|
||||||
return bridge {
|
return bridge(error) {
|
||||||
|
|
||||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
do {
|
||||||
|
|
||||||
closure(transaction.bridgeToObjectiveC)
|
try self.bridgeToSwift.perform(
|
||||||
|
synchronous: { (transaction) in
|
||||||
|
|
||||||
|
let csTransaction = transaction.bridgeToObjectiveC
|
||||||
|
closure(csTransaction)
|
||||||
|
if !transaction.isCommitted && transaction.hasChanges {
|
||||||
|
|
||||||
|
CoreStore.log(
|
||||||
|
.warning,
|
||||||
|
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
try transaction.cancel()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch CoreStoreError.userCancelled {
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,4 +131,21 @@ public extension CSDataStack {
|
|||||||
|
|
||||||
self.bridgeToSwift.refreshAndMergeAllObjects()
|
self.bridgeToSwift.refreshAndMergeAllObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -[CSDataStack beginSynchronous:error:] API that reports failure using an error instance.")
|
||||||
|
@objc
|
||||||
|
@discardableResult
|
||||||
|
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||||
|
|
||||||
|
return bridge {
|
||||||
|
|
||||||
|
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||||
|
|
||||||
|
closure(transaction.bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -49,75 +49,22 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
|||||||
/**
|
/**
|
||||||
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
|
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
|
||||||
|
|
||||||
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
|
- parameter xcodeModelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
|
||||||
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
|
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
|
||||||
- parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
- parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(modelName: String?, bundle: Bundle?, versionChain: [String]?) {
|
public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
DataStack(
|
DataStack(
|
||||||
modelName: modelName ?? DataStack.applicationName,
|
xcodeModelName: xcodeModelName ?? DataStack.applicationName,
|
||||||
bundle: bundle ?? Bundle.main,
|
bundle: bundle ?? Bundle.main,
|
||||||
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
|
|
||||||
|
|
||||||
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
|
|
||||||
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
|
|
||||||
- parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public convenience init(modelName: String?, bundle: Bundle?, versionTree: [String: String]?) {
|
|
||||||
|
|
||||||
self.init(
|
|
||||||
DataStack(
|
|
||||||
modelName: modelName ?? DataStack.applicationName,
|
|
||||||
bundle: bundle ?? Bundle.main,
|
|
||||||
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Initializes a `DataStack` from an `NSManagedObjectModel`.
|
|
||||||
|
|
||||||
- parameter model: the `NSManagedObjectModel` for the stack
|
|
||||||
- parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
|
|
||||||
|
|
||||||
self.init(
|
|
||||||
DataStack(
|
|
||||||
model: model,
|
|
||||||
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Initializes a `DataStack` from an `NSManagedObjectModel`.
|
|
||||||
|
|
||||||
- parameter model: the `NSManagedObjectModel` for the stack
|
|
||||||
- parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
|
|
||||||
|
|
||||||
self.init(
|
|
||||||
DataStack(
|
|
||||||
model: model,
|
|
||||||
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
|
Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
|
||||||
*/
|
*/
|
||||||
@@ -128,23 +75,12 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the entity name-to-class type mapping from the stack's model.
|
Returns the entity name-to-class type mapping from the `CSDataStack`'s model.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var entityClassesByName: [String: NSManagedObject.Type] {
|
public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||||
|
|
||||||
return self.bridgeToSwift.entityTypesByName
|
return self.bridgeToSwift.entityTypesByName(for: type)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the entity class for the given entity name from the stack's's model.
|
|
||||||
- parameter name: the entity name
|
|
||||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
public func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
|
|
||||||
|
|
||||||
return self.bridgeToSwift.entityTypesByName[name]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,7 +106,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
return bridge(error) {
|
return bridge(error) {
|
||||||
|
|
||||||
try self.bridgeToSwift.addStorageAndWait(InMemoryStore.self)
|
try self.bridgeToSwift.addStorageAndWait(InMemoryStore())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +124,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
return bridge(error) {
|
return bridge(error) {
|
||||||
|
|
||||||
try self.bridgeToSwift.addStorageAndWait(SQLiteStore.self)
|
try self.bridgeToSwift.addStorageAndWait(SQLiteStore())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +204,60 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
|||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the -[initWithXcodeModelName:bundle:versionChain:] initializer.")
|
||||||
|
@objc
|
||||||
|
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
DataStack(
|
||||||
|
xcodeModelName: modelName ?? DataStack.applicationName,
|
||||||
|
bundle: bundle ?? Bundle.main,
|
||||||
|
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
|
||||||
|
@objc
|
||||||
|
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
DataStack(
|
||||||
|
model: model,
|
||||||
|
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionTree:] initializer.")
|
||||||
|
@objc
|
||||||
|
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
DataStack(
|
||||||
|
model: model,
|
||||||
|
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||||
|
@objc
|
||||||
|
public var entityClassesByName: [EntityName: NSManagedObject.Type] {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.entityTypesByName
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||||
|
@objc
|
||||||
|
public func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.entityTypesByName[name]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// CSDynamicSchema.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: - CSDynamicSchema
|
||||||
|
|
||||||
|
/**
|
||||||
|
The `CSDynamicSchema` serves as the Objective-C bridging type for `DynamicSchema`.
|
||||||
|
|
||||||
|
- SeeAlso: `DynamicSchema`
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
public protocol CSDynamicSchema {
|
||||||
|
|
||||||
|
/**
|
||||||
|
The version string for this model schema.
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
var modelVersion: ModelVersion { get }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Do not call this directly. The `NSManagedObjectModel` for this schema may be created lazily and using this method directly may affect the integrity of the model.
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
func rawModel() -> NSManagedObjectModel
|
||||||
|
}
|
||||||
@@ -137,6 +137,16 @@ public enum CSErrorCode: Int {
|
|||||||
An internal SDK call failed with the specified "NSError" userInfo key.
|
An internal SDK call failed with the specified "NSError" userInfo key.
|
||||||
*/
|
*/
|
||||||
case internalError
|
case internalError
|
||||||
|
|
||||||
|
/**
|
||||||
|
The transaction was terminated by a user-thrown error with the specified "Error" userInfo key.
|
||||||
|
*/
|
||||||
|
case userError
|
||||||
|
|
||||||
|
/**
|
||||||
|
The transaction was cancelled by the user.
|
||||||
|
*/
|
||||||
|
case userCancelled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -209,12 +219,23 @@ extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
|
|||||||
self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
|
self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
|
||||||
|
|
||||||
case .internalError:
|
case .internalError:
|
||||||
guard case let NSError as NSError = info["NSError"] else {
|
guard case let nsError as NSError = info["NSError"] else {
|
||||||
|
|
||||||
self = .unknown
|
self = .unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self = .internalError(NSError: NSError)
|
self = .internalError(NSError: nsError)
|
||||||
|
|
||||||
|
case .userError:
|
||||||
|
guard case let error as Error = info["Error"] else {
|
||||||
|
|
||||||
|
self = .unknown
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self = .userError(error: error)
|
||||||
|
|
||||||
|
case .userCancelled:
|
||||||
|
self = .userCancelled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ import CoreData
|
|||||||
- SeeAlso: `From`
|
- SeeAlso: `From`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
public final class CSFrom: NSObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The associated `NSManagedObject` entity class
|
The associated `NSManagedObject` entity class
|
||||||
@@ -71,7 +71,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
|||||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(entityClass: AnyClass) {
|
public convenience init(entityClass: NSManagedObject.Type) {
|
||||||
|
|
||||||
self.init(From(entityClass))
|
self.init(From(entityClass))
|
||||||
}
|
}
|
||||||
@@ -82,10 +82,11 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
|||||||
MyPersonEntity *people = [transaction fetchAllFrom:
|
MyPersonEntity *people = [transaction fetchAllFrom:
|
||||||
CSFromClass([MyPersonEntity class], @"Config1")];
|
CSFromClass([MyPersonEntity class], @"Config1")];
|
||||||
```
|
```
|
||||||
|
- parameter entityClass: the associated `NSManagedObject` entity class
|
||||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(entityClass: AnyClass, configuration: Any) {
|
public convenience init(entityClass: NSManagedObject.Type, configuration: Any) {
|
||||||
|
|
||||||
switch configuration {
|
switch configuration {
|
||||||
|
|
||||||
@@ -107,13 +108,13 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
|||||||
CSFromClass([MyPersonEntity class],
|
CSFromClass([MyPersonEntity class],
|
||||||
@[[NSNull null], @"Config1"])];
|
@[[NSNull null], @"Config1"])];
|
||||||
```
|
```
|
||||||
- parameter entity: the associated `NSManagedObject` entity class
|
- parameter entityClass: the associated `NSManagedObject` entity class
|
||||||
- parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
- parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(entityClass: AnyClass, configurations: [Any]) {
|
public convenience init(entityClass: NSManagedObject.Type, configurations: [Any]) {
|
||||||
|
|
||||||
var arguments = [String?]()
|
var arguments = [ModelConfiguration]()
|
||||||
for configuration in configurations {
|
for configuration in configurations {
|
||||||
|
|
||||||
switch configuration {
|
switch configuration {
|
||||||
@@ -144,7 +145,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
public let bridgeToSwift: From<NSManagedObject>
|
public let bridgeToSwift: From<NSManagedObject>
|
||||||
|
|
||||||
public init<T: NSManagedObject>(_ swiftValue: From<T>) {
|
public init<D: NSManagedObject>(_ swiftValue: From<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue.downcast()
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
@@ -154,7 +155,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - From
|
// MARK: - From
|
||||||
|
|
||||||
extension From: CoreStoreSwiftType {
|
extension From where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -162,4 +163,16 @@ extension From: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSFrom(self)
|
return CSFrom(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> From<NSManagedObject> {
|
||||||
|
|
||||||
|
return From<NSManagedObject>(
|
||||||
|
entityClass: self.entityClass,
|
||||||
|
configurations: self.configurations,
|
||||||
|
findPersistentStores: self.findPersistentStores
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -35,13 +35,13 @@ import CoreData
|
|||||||
- SeeAlso: `GroupBy`
|
- SeeAlso: `GroupBy`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
|
public final class CSGroupBy: NSObject, CSQueryClause {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The list of key path strings to group results with
|
The list of key path strings to group results with
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var keyPaths: [KeyPath] {
|
public var keyPaths: [KeyPathString] {
|
||||||
|
|
||||||
return self.bridgeToSwift.keyPaths
|
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
|
- parameter keyPath: a key path string to group results with
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(keyPath: KeyPath) {
|
public convenience init(keyPath: KeyPathString) {
|
||||||
|
|
||||||
self.init(GroupBy(keyPath))
|
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
|
- parameter keyPaths: a list of key path strings to group results with
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(keyPaths: [KeyPath]) {
|
public convenience init(keyPaths: [KeyPathString]) {
|
||||||
|
|
||||||
self.init(GroupBy(keyPaths))
|
self.init(GroupBy(keyPaths))
|
||||||
}
|
}
|
||||||
@@ -102,11 +102,11 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
public let bridgeToSwift: GroupBy
|
public let bridgeToSwift: GroupBy<NSManagedObject>
|
||||||
|
|
||||||
public init(_ swiftValue: GroupBy) {
|
public init<D: NSManagedObject>(_ swiftValue: GroupBy<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - GroupBy
|
// MARK: - GroupBy
|
||||||
|
|
||||||
extension GroupBy: CoreStoreSwiftType {
|
extension GroupBy where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -122,4 +122,12 @@ extension GroupBy: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSGroupBy(self)
|
return CSGroupBy(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> GroupBy<NSManagedObject> {
|
||||||
|
|
||||||
|
return GroupBy<NSManagedObject>(self.keyPaths)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
|
|||||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
|
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(configuration: String?) {
|
public convenience init(configuration: ModelConfiguration) {
|
||||||
|
|
||||||
self.init(InMemoryStore(configuration: configuration))
|
self.init(InMemoryStore(configuration: configuration))
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
|
|||||||
The configuration name in the model file
|
The configuration name in the model file
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var configuration: String? {
|
public var configuration: ModelConfiguration {
|
||||||
|
|
||||||
return self.bridgeToSwift.configuration
|
return self.bridgeToSwift.configuration
|
||||||
}
|
}
|
||||||
@@ -35,13 +35,13 @@ import CoreData
|
|||||||
- SeeAlso: `Into`
|
- SeeAlso: `Into`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
public final class CSInto: NSObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The associated `NSManagedObject` entity class
|
The associated `NSManagedObject` entity class
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var entityClass: AnyClass {
|
public var entityClass: NSManagedObject.Type {
|
||||||
|
|
||||||
return self.bridgeToSwift.entityClass
|
return self.bridgeToSwift.entityClass
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
|||||||
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
|
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var configuration: String? {
|
public var configuration: ModelConfiguration {
|
||||||
|
|
||||||
return self.bridgeToSwift.configuration
|
return self.bridgeToSwift.configuration
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
|||||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(entityClass: AnyClass) {
|
public convenience init(entityClass: NSManagedObject.Type) {
|
||||||
|
|
||||||
self.init(Into(entityClass))
|
self.init(Into(entityClass))
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
|||||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(entityClass: AnyClass, configuration: String?) {
|
public convenience init(entityClass: NSManagedObject.Type, configuration: ModelConfiguration) {
|
||||||
|
|
||||||
self.init(Into(entityClass, configuration))
|
self.init(Into(entityClass, configuration))
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
public let bridgeToSwift: Into<NSManagedObject>
|
public let bridgeToSwift: Into<NSManagedObject>
|
||||||
|
|
||||||
public required init<T: NSManagedObject>(_ swiftValue: Into<T>) {
|
public required init<D: NSManagedObject>(_ swiftValue: Into<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue.downcast()
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
@@ -122,7 +122,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - Into
|
// MARK: - Into
|
||||||
|
|
||||||
extension Into: CoreStoreSwiftType {
|
extension Into where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -130,4 +130,16 @@ extension Into: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSInto(self)
|
return CSInto(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> Into<NSManagedObject> {
|
||||||
|
|
||||||
|
return Into<NSManagedObject>(
|
||||||
|
entityClass: self.entityClass,
|
||||||
|
configuration: self.configuration,
|
||||||
|
inferStoreIfPossible: self.inferStoreIfPossible
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -27,8 +27,6 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSListMonitor
|
// MARK: - CSListMonitor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,8 +34,9 @@ import CoreData
|
|||||||
|
|
||||||
- SeeAlso: `ListMonitor`
|
- SeeAlso: `ListMonitor`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
|
public final class CSListMonitor: NSObject {
|
||||||
|
|
||||||
// MARK: Public (Accessors)
|
// MARK: Public (Accessors)
|
||||||
|
|
||||||
@@ -546,7 +545,8 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - ListMonitor
|
// MARK: - ListMonitor
|
||||||
|
|
||||||
extension ListMonitor: CoreStoreSwiftType {
|
@available(OSX 10.12, *)
|
||||||
|
extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -554,6 +554,16 @@ extension ListMonitor: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSListMonitor(self)
|
return CSListMonitor(self)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> ListMonitor<NSManagedObject> {
|
||||||
|
|
||||||
|
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||||
|
|
||||||
|
return unsafeBitCast(x, to: type)
|
||||||
|
}
|
||||||
|
return noWarnUnsafeBitCast(self, to: ListMonitor<NSManagedObject>.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,8 +27,6 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSListObserver
|
// MARK: - CSListObserver
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,8 +40,9 @@ import CoreData
|
|||||||
|
|
||||||
- SeeAlso: `ListObserver`
|
- SeeAlso: `ListObserver`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public protocol CSListObserver: class, AnyObject {
|
public protocol CSListObserver: class {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Handles processing just before a change to the observed list occurs
|
Handles processing just before a change to the observed list occurs
|
||||||
@@ -92,6 +91,7 @@ public protocol CSListObserver: class, AnyObject {
|
|||||||
|
|
||||||
- SeeAlso: `ListObjectObserver`
|
- SeeAlso: `ListObjectObserver`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public protocol CSListObjectObserver: CSListObserver {
|
public protocol CSListObjectObserver: CSListObserver {
|
||||||
|
|
||||||
@@ -152,6 +152,7 @@ public protocol CSListObjectObserver: CSListObserver {
|
|||||||
|
|
||||||
- SeeAlso: `ListSectionObserver`
|
- SeeAlso: `ListSectionObserver`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public protocol CSListSectionObserver: CSListObjectObserver {
|
public protocol CSListSectionObserver: CSListObjectObserver {
|
||||||
|
|
||||||
@@ -175,5 +176,3 @@ public protocol CSListSectionObserver: CSListObjectObserver {
|
|||||||
@objc
|
@objc
|
||||||
optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
|
optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -27,8 +27,6 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSObjectMonitor
|
// MARK: - CSObjectMonitor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,8 +34,9 @@ import CoreData
|
|||||||
|
|
||||||
- SeeAlso: `ObjectMonitor`
|
- SeeAlso: `ObjectMonitor`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
|
public final class CSObjectMonitor: NSObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
|
Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
|
||||||
@@ -138,7 +137,8 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - ObjectMonitor
|
// MARK: - ObjectMonitor
|
||||||
|
|
||||||
extension ObjectMonitor: CoreStoreSwiftType {
|
@available(OSX 10.12, *)
|
||||||
|
extension ObjectMonitor where ObjectMonitor.ObjectType: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -146,6 +146,16 @@ extension ObjectMonitor: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSObjectMonitor(self)
|
return CSObjectMonitor(self)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> ObjectMonitor<NSManagedObject> {
|
||||||
|
|
||||||
|
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||||
|
|
||||||
|
return unsafeBitCast(x, to: type)
|
||||||
|
}
|
||||||
|
return noWarnUnsafeBitCast(self, to: ObjectMonitor<NSManagedObject>.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,8 +27,6 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSObjectObserver
|
// MARK: - CSObjectObserver
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,8 +38,9 @@ import CoreData
|
|||||||
|
|
||||||
- SeeAlso: `ObjectObserver`
|
- SeeAlso: `ObjectObserver`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public protocol CSObjectObserver: class, AnyObject {
|
public protocol CSObjectObserver: class {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Handles processing just before a change to the observed `object` occurs
|
Handles processing just before a change to the observed `object` occurs
|
||||||
@@ -71,5 +70,3 @@ public protocol CSObjectObserver: class, AnyObject {
|
|||||||
@objc
|
@objc
|
||||||
optional func objectMonitor(_ monitor: CSObjectMonitor, didDeleteObject object: Any)
|
optional func objectMonitor(_ monitor: CSObjectMonitor, didDeleteObject object: Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -35,7 +35,7 @@ import CoreData
|
|||||||
- SeeAlso: `OrderBy`
|
- SeeAlso: `OrderBy`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause, CoreStoreObjectiveCType {
|
public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The list of sort descriptors
|
The list of sort descriptors
|
||||||
@@ -110,11 +110,11 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
public let bridgeToSwift: OrderBy
|
public let bridgeToSwift: OrderBy<NSManagedObject>
|
||||||
|
|
||||||
public init(_ swiftValue: OrderBy) {
|
public init<D: NSManagedObject>(_ swiftValue: OrderBy<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
|
|||||||
|
|
||||||
// MARK: - OrderBy
|
// MARK: - OrderBy
|
||||||
|
|
||||||
extension OrderBy: CoreStoreSwiftType {
|
extension OrderBy where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -130,4 +130,12 @@ extension OrderBy: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSOrderBy(self)
|
return CSOrderBy(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> OrderBy<NSManagedObject> {
|
||||||
|
|
||||||
|
return OrderBy<NSManagedObject>(self.sortDescriptors)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -40,19 +40,18 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
|||||||
/**
|
/**
|
||||||
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
||||||
|
|
||||||
|
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||||
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
|
|
||||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
|
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(fileURL: URL, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
public convenience init(fileURL: URL, configuration: ModelConfiguration, localStorageOptions: Int) {
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
SQLiteStore(
|
SQLiteStore(
|
||||||
fileURL: fileURL,
|
fileURL: fileURL,
|
||||||
configuration: configuration,
|
configuration: configuration,
|
||||||
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
|
|
||||||
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -61,29 +60,27 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
|||||||
/**
|
/**
|
||||||
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
||||||
|
|
||||||
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
|
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||||
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
|
|
||||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
|
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(fileName: String, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
public convenience init(fileName: String, configuration: ModelConfiguration, localStorageOptions: Int) {
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
SQLiteStore(
|
SQLiteStore(
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
configuration: configuration,
|
configuration: configuration,
|
||||||
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
|
|
||||||
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`.
|
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
|
||||||
|
|
||||||
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
|
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience override init() {
|
public convenience override init() {
|
||||||
@@ -104,12 +101,12 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The `NSBundle`s from which to search mapping models for migrations
|
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var mappingModelBundles: [Bundle] {
|
public var migrationMappingProviders: [Any] {
|
||||||
|
|
||||||
return self.bridgeToSwift.mappingModelBundles
|
return self.bridgeToSwift.migrationMappingProviders
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +130,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
|||||||
/**
|
/**
|
||||||
The configuration name in the model file
|
The configuration name in the model file
|
||||||
*/
|
*/
|
||||||
public var configuration: String? {
|
public var configuration: ModelConfiguration {
|
||||||
|
|
||||||
return self.bridgeToSwift.configuration
|
return self.bridgeToSwift.configuration
|
||||||
}
|
}
|
||||||
@@ -154,11 +151,11 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
|||||||
Called by the `CSDataStack` 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 `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
|
Called by the `CSDataStack` 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 `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
|
public func cs_eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
|
||||||
|
|
||||||
return bridge(error) {
|
return bridge(error) {
|
||||||
|
|
||||||
try self.bridgeToSwift.eraseStorageAndWait(metadata: metadata as! [String: Any], soureModelHint: soureModelHint)
|
try self.bridgeToSwift.cs_eraseStorageAndWait(metadata: metadata as! [String: Any], soureModelHint: soureModelHint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +191,23 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
|||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Obsoleted
|
||||||
|
|
||||||
|
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileURL:configuration:localStorageOptions:]) initializer instead.")
|
||||||
|
@objc
|
||||||
|
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||||
|
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileName:configuration:localStorageOptions:]) initializer instead.")
|
||||||
|
@objc
|
||||||
|
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||||
|
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -29,35 +29,22 @@ import CoreData
|
|||||||
|
|
||||||
// MARK: - CSSaveResult
|
// MARK: - CSSaveResult
|
||||||
|
|
||||||
/**
|
@available(*, deprecated, message: "Use APIs that report failures with `CSError`s instead.")
|
||||||
The `CSSaveResult` serves as the Objective-C bridging type for `SaveResult`.
|
|
||||||
|
|
||||||
- SeeAlso: `SaveResult`
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
||||||
|
|
||||||
/**
|
|
||||||
`YES` if the `commit` operation for the transaction succeeded, either because the save succeeded or because there were no changes to save. Returns `NO` to indicate failure.
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public var isSuccess: Bool {
|
public var isSuccess: Bool {
|
||||||
|
|
||||||
return self.bridgeToSwift.boolValue
|
return self.bridgeToSwift.boolValue
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
`YES` if the `commit` operation for the transaction failed, or `NO` otherwise. When `YES`, the `error` property returns the actual `NSError` for the failure.
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public var isFailure: Bool {
|
public var isFailure: Bool {
|
||||||
|
|
||||||
return !self.bridgeToSwift.boolValue
|
return !self.bridgeToSwift.boolValue
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
`YES` if the `commit` operation for the transaction succeeded and if there was an actual change made. Returns `NO` otherwise.
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public var hasChanges: Bool {
|
public var hasChanges: Bool {
|
||||||
|
|
||||||
@@ -68,9 +55,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
|||||||
return hasChanges
|
return hasChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
The `NSError` for a failed `commit` operation, or `nil` if the `commit` succeeded
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public var error: NSError? {
|
public var error: NSError? {
|
||||||
|
|
||||||
@@ -81,14 +65,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
|||||||
return error.bridgeToObjectiveC
|
return error.bridgeToObjectiveC
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
If the result was a success, the `success` block is executed with a `BOOL` argument that indicates if there were any changes made. If the result was a failure, the `failure` block is executed with an `NSError` argument pertaining to the actual error.
|
|
||||||
|
|
||||||
The blocks are executed immediately as `@noescape` and will not be retained.
|
|
||||||
|
|
||||||
- parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made.
|
|
||||||
- parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void, failure: (_ error: NSError) -> Void) {
|
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void, failure: (_ error: NSError) -> Void) {
|
||||||
|
|
||||||
@@ -102,13 +78,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
If the result was a success, the `success` block is executed with a `BOOL` argument that indicates if there were any changes made. If the result was a failure, this method does nothing.
|
|
||||||
|
|
||||||
The block is executed immediately as `@noescape` and will not be retained.
|
|
||||||
|
|
||||||
- parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made.
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void) {
|
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void) {
|
||||||
|
|
||||||
@@ -119,13 +88,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
|||||||
success(hasChanges)
|
success(hasChanges)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
If the result was a failure, the `failure` block is executed with an `NSError` argument pertaining to the actual error. If the result was a success, this method does nothing.
|
|
||||||
|
|
||||||
The block is executed immediately as `@noescape` and will not be retained.
|
|
||||||
|
|
||||||
- parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
|
|
||||||
*/
|
|
||||||
@objc
|
@objc
|
||||||
public func handleFailure(_ failure: (_ error: NSError) -> Void) {
|
public func handleFailure(_ failure: (_ error: NSError) -> Void) {
|
||||||
|
|
||||||
@@ -173,6 +135,7 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - SaveResult
|
// MARK: - SaveResult
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new DataStack.perform(asynchronous:...) and DataStack.perform(synchronous:...) family of APIs")
|
||||||
extension SaveResult: CoreStoreSwiftType {
|
extension SaveResult: CoreStoreSwiftType {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
@@ -27,8 +27,6 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - CSSectionBy
|
// MARK: - CSSectionBy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,8 +34,9 @@ import CoreData
|
|||||||
|
|
||||||
- SeeAlso: `SectionBy`
|
- SeeAlso: `SectionBy`
|
||||||
*/
|
*/
|
||||||
|
@available(OSX 10.12, *)
|
||||||
@objc
|
@objc
|
||||||
public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
public final class CSSectionBy: NSObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initializes a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
Initializes a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
||||||
@@ -46,9 +45,9 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
|||||||
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func keyPath(_ sectionKeyPath: KeyPath) -> CSSectionBy {
|
public static func keyPath(_ sectionKeyPath: KeyPathString) -> CSSectionBy {
|
||||||
|
|
||||||
return self.init(SectionBy(sectionKeyPath))
|
return self.init(SectionBy<NSManagedObject>(sectionKeyPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,9 +58,9 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
|||||||
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func keyPath(_ sectionKeyPath: KeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
|
public static func keyPath(_ sectionKeyPath: KeyPathString, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
|
||||||
|
|
||||||
return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer))
|
return self.init(SectionBy<NSManagedObject>(sectionKeyPath, sectionIndexTransformer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -75,11 +74,11 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
public let bridgeToSwift: SectionBy
|
public let bridgeToSwift: SectionBy<NSManagedObject>
|
||||||
|
|
||||||
public init(_ swiftValue: SectionBy) {
|
public init<D>(_ swiftValue: SectionBy<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +86,8 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - SectionBy
|
// MARK: - SectionBy
|
||||||
|
|
||||||
extension SectionBy: CoreStoreSwiftType {
|
@available(OSX 10.12, *)
|
||||||
|
extension SectionBy {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -95,6 +95,12 @@ extension SectionBy: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSSectionBy(self)
|
return CSSectionBy(self)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> SectionBy<NSManagedObject> {
|
||||||
|
|
||||||
|
return SectionBy<NSManagedObject>(self.sectionKeyPath, self.sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ import CoreData
|
|||||||
- SeeAlso: `SelectTerm`
|
- SeeAlso: `SelectTerm`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
public final class CSSelectTerm: NSObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Provides a `CSSelectTerm` to a `CSSelect` clause for querying an entity attribute.
|
Provides a `CSSelectTerm` to a `CSSelect` clause for querying an entity attribute.
|
||||||
@@ -48,7 +48,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
|||||||
- parameter keyPath: the attribute name
|
- parameter keyPath: the attribute name
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(keyPath: KeyPath) {
|
public convenience init(keyPath: KeyPathString) {
|
||||||
|
|
||||||
self.init(.attribute(keyPath))
|
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
|
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
public static func average(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
|
||||||
|
|
||||||
return self.init(.average(keyPath, as: alias))
|
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
|
- returns: a `SelectTerm` to a `Select` clause for a count query
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
public static func count(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
|
||||||
|
|
||||||
return self.init(.count(keyPath, as: alias))
|
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
|
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
public static func maximum(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
|
||||||
|
|
||||||
return self.init(.maximum(keyPath, as: alias))
|
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
|
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
public static func minimum(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
|
||||||
|
|
||||||
return self.init(.minimum(keyPath, as: alias))
|
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
|
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
|
public static func sum(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
|
||||||
|
|
||||||
return self.init(.sum(keyPath, as: alias))
|
return self.init(.sum(keyPath, as: alias))
|
||||||
}
|
}
|
||||||
@@ -146,12 +146,11 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
|||||||
select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]]
|
select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]]
|
||||||
fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
|
fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
|
||||||
```
|
```
|
||||||
- parameter keyPath: the attribute name
|
|
||||||
- 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
|
- 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
|
- returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm {
|
public static func objectIDAs(_ alias: KeyPathString? = nil) -> CSSelectTerm {
|
||||||
|
|
||||||
return self.init(.objectID(as: alias))
|
return self.init(.objectID(as: alias))
|
||||||
}
|
}
|
||||||
@@ -176,11 +175,11 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
public let bridgeToSwift: SelectTerm
|
public let bridgeToSwift: SelectTerm<NSManagedObject>
|
||||||
|
|
||||||
public init(_ swiftValue: SelectTerm) {
|
public init<D: NSManagedObject>(_ swiftValue: SelectTerm<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +187,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
|
|||||||
|
|
||||||
// MARK: - SelectTerm
|
// MARK: - SelectTerm
|
||||||
|
|
||||||
extension SelectTerm: CoreStoreSwiftType {
|
extension SelectTerm where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -196,6 +195,24 @@ extension SelectTerm: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSSelectTerm(self)
|
return CSSelectTerm(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> SelectTerm<NSManagedObject> {
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
|
||||||
|
case ._attribute(let keyPath):
|
||||||
|
return SelectTerm<NSManagedObject>._attribute(keyPath)
|
||||||
|
|
||||||
|
case ._aggregate(let function, let keyPath, let alias, let nativeType):
|
||||||
|
return SelectTerm<NSManagedObject>._aggregate(function: function, keyPath: keyPath, alias: alias, nativeType: nativeType)
|
||||||
|
|
||||||
|
case ._identity(let alias, let nativeType):
|
||||||
|
return SelectTerm<NSManagedObject>._identity(alias: alias, nativeType: nativeType)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -217,11 +234,12 @@ public final class CSSelect: NSObject {
|
|||||||
select:CSSelectNumber(CSAggregateMax(@"age"))
|
select:CSSelectNumber(CSAggregateMax(@"age"))
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
- parameter numberTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public convenience init(numberTerm: CSSelectTerm) {
|
public convenience init(numberTerm: CSSelectTerm) {
|
||||||
|
|
||||||
self.init(Select<NSNumber>(numberTerm.bridgeToSwift))
|
self.init(Select<NSManagedObject, NSNumber>(numberTerm.bridgeToSwift))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,11 +250,12 @@ public final class CSSelect: NSObject {
|
|||||||
select:CSSelectDecimal(CSAggregateAverage(@"price"))
|
select:CSSelectDecimal(CSAggregateAverage(@"price"))
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
- parameter decimalTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public convenience init(decimalTerm: CSSelectTerm) {
|
public convenience init(decimalTerm: CSSelectTerm) {
|
||||||
|
|
||||||
self.init(Select<NSDecimalNumber>(decimalTerm.bridgeToSwift))
|
self.init(Select<NSManagedObject, NSDecimalNumber>(decimalTerm.bridgeToSwift))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,11 +266,12 @@ public final class CSSelect: NSObject {
|
|||||||
select:CSSelectString(CSAttribute(@"fullname"))
|
select:CSSelectString(CSAttribute(@"fullname"))
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
- parameter stringTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public convenience init(stringTerm: CSSelectTerm) {
|
public convenience init(stringTerm: CSSelectTerm) {
|
||||||
|
|
||||||
self.init(Select<NSString>(stringTerm.bridgeToSwift))
|
self.init(Select<NSManagedObject, NSString>(stringTerm.bridgeToSwift))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,11 +282,12 @@ public final class CSSelect: NSObject {
|
|||||||
select:CSSelectDate(CSAggregateMax(@"updatedDate"))
|
select:CSSelectDate(CSAggregateMax(@"updatedDate"))
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
- parameter dateTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public convenience init(dateTerm: CSSelectTerm) {
|
public convenience init(dateTerm: CSSelectTerm) {
|
||||||
|
|
||||||
self.init(Select<Date>(dateTerm.bridgeToSwift))
|
self.init(Select<NSManagedObject, Date>(dateTerm.bridgeToSwift))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -277,11 +298,12 @@ public final class CSSelect: NSObject {
|
|||||||
select:CSSelectData(CSAttribute(@"imageData"))
|
select:CSSelectData(CSAttribute(@"imageData"))
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
- parameter dataTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public convenience init(dataTerm: CSSelectTerm) {
|
public convenience init(dataTerm: CSSelectTerm) {
|
||||||
|
|
||||||
self.init(Select<Data>(dataTerm.bridgeToSwift))
|
self.init(Select<NSManagedObject, Data>(dataTerm.bridgeToSwift))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -292,11 +314,11 @@ public final class CSSelect: NSObject {
|
|||||||
select:CSSelectObjectID()
|
select:CSSelectObjectID()
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public convenience init(objectIDTerm: ()) {
|
public convenience init(objectIDTerm: ()) {
|
||||||
|
|
||||||
self.init(Select<NSManagedObjectID>(.objectID()))
|
self.init(Select<NSManagedObject, NSManagedObjectID>(.objectID()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,9 +331,10 @@ public final class CSSelect: NSObject {
|
|||||||
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
|
||||||
- returns: a `CSSelect` clause for querying an entity attribute
|
- returns: a `CSSelect` clause for querying an entity attribute
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public static func dictionaryForTerm(_ term: CSSelectTerm) -> CSSelect {
|
public static func dictionaryForTerm(_ term: CSSelectTerm) -> CSSelect {
|
||||||
|
|
||||||
return self.init(Select<NSDictionary>(term.bridgeToSwift))
|
return self.init(Select<NSManagedObject, NSDictionary>(term.bridgeToSwift))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -327,9 +350,10 @@ public final class CSSelect: NSObject {
|
|||||||
- parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query
|
- parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query
|
||||||
- returns: a `CSSelect` clause for querying an entity attribute
|
- returns: a `CSSelect` clause for querying an entity attribute
|
||||||
*/
|
*/
|
||||||
|
@objc
|
||||||
public static func dictionaryForTerms(_ terms: [CSSelectTerm]) -> CSSelect {
|
public static func dictionaryForTerms(_ terms: [CSSelectTerm]) -> CSSelect {
|
||||||
|
|
||||||
return self.init(Select<NSDictionary>(terms.map { $0.bridgeToSwift }))
|
return self.init(Select<NSManagedObject, NSDictionary>(terms.map { $0.bridgeToSwift }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -359,18 +383,18 @@ public final class CSSelect: NSObject {
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
public init<T: SelectValueResultType>(_ swiftValue: Select<T>) {
|
public init<D: NSManagedObject, T: QueryableAttributeType>(_ swiftValue: Select<D, T>) {
|
||||||
|
|
||||||
self.attributeType = T.attributeType
|
self.attributeType = T.cs_rawAttributeType
|
||||||
self.selectTerms = swiftValue.selectTerms
|
self.selectTerms = swiftValue.selectTerms.map({ $0.downcast() })
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
public init<T: SelectResultType>(_ swiftValue: Select<T>) {
|
public init<D: NSManagedObject, T>(_ swiftValue: Select<D, T>) {
|
||||||
|
|
||||||
self.attributeType = .undefinedAttributeType
|
self.attributeType = .undefinedAttributeType
|
||||||
self.selectTerms = swiftValue.selectTerms
|
self.selectTerms = swiftValue.selectTerms.map({ $0.downcast() })
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
@@ -379,7 +403,95 @@ public final class CSSelect: NSObject {
|
|||||||
// MARK: Internal
|
// MARK: Internal
|
||||||
|
|
||||||
internal let attributeType: NSAttributeType
|
internal let attributeType: NSAttributeType
|
||||||
internal let selectTerms: [SelectTerm]
|
internal let selectTerms: [SelectTerm<NSManagedObject>]
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Internal
|
||||||
|
|
||||||
|
internal func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
|
||||||
|
|
||||||
|
fetchRequest.includesPendingChanges = false
|
||||||
|
fetchRequest.resultType = .dictionaryResultType
|
||||||
|
|
||||||
|
func attributeDescription(for keyPath: String, in entity: NSEntityDescription) -> NSAttributeDescription? {
|
||||||
|
|
||||||
|
let components = keyPath.components(separatedBy: ".")
|
||||||
|
switch components.count {
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return entity.attributesByName[components[0]]
|
||||||
|
|
||||||
|
default:
|
||||||
|
guard let relationship = entity.relationshipsByName[components[0]],
|
||||||
|
let destinationEntity = relationship.destinationEntity else {
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return attributeDescription(
|
||||||
|
for: components.dropFirst().joined(separator: "."),
|
||||||
|
in: destinationEntity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertiesToFetch = [Any]()
|
||||||
|
for term in self.selectTerms {
|
||||||
|
|
||||||
|
switch term {
|
||||||
|
|
||||||
|
case ._attribute(let keyPath):
|
||||||
|
propertiesToFetch.append(keyPath)
|
||||||
|
|
||||||
|
case ._aggregate(let function, let keyPath, let alias, let nativeType):
|
||||||
|
let entityDescription = fetchRequest.entity!
|
||||||
|
if let attributeDescription = attributeDescription(for: keyPath, in: entityDescription) {
|
||||||
|
|
||||||
|
let expressionDescription = NSExpressionDescription()
|
||||||
|
expressionDescription.name = alias
|
||||||
|
if nativeType == .undefinedAttributeType {
|
||||||
|
|
||||||
|
expressionDescription.expressionResultType = attributeDescription.attributeType
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
expressionDescription.expressionResultType = nativeType
|
||||||
|
}
|
||||||
|
expressionDescription.expression = NSExpression(
|
||||||
|
forFunction: function,
|
||||||
|
arguments: [NSExpression(forKeyPath: keyPath)]
|
||||||
|
)
|
||||||
|
propertiesToFetch.append(expressionDescription)
|
||||||
|
}
|
||||||
|
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(self)) query clause."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
case ._identity(let alias, let nativeType):
|
||||||
|
let expressionDescription = NSExpressionDescription()
|
||||||
|
expressionDescription.name = alias
|
||||||
|
if nativeType == .undefinedAttributeType {
|
||||||
|
|
||||||
|
expressionDescription.expressionResultType = .objectIDAttributeType
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
expressionDescription.expressionResultType = nativeType
|
||||||
|
}
|
||||||
|
expressionDescription.expression = NSExpression.expressionForEvaluatedObject()
|
||||||
|
|
||||||
|
propertiesToFetch.append(expressionDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchRequest.propertiesToFetch = propertiesToFetch
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
@@ -390,7 +502,7 @@ public final class CSSelect: NSObject {
|
|||||||
|
|
||||||
// MARK: - Select
|
// MARK: - Select
|
||||||
|
|
||||||
extension Select: CoreStoreSwiftType {
|
extension Select where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -398,4 +510,12 @@ extension Select: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSSelect(self)
|
return CSSelect(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> Select<NSManagedObject, T> {
|
||||||
|
|
||||||
|
return Select<NSManagedObject, T>(self.selectTerms.map({ $0.downcast() }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ public final class CSSetupResult: NSObject {
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// 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 {
|
switch swiftValue {
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public protocol CSStorageInterface {
|
|||||||
The configuration name in the model file
|
The configuration name in the model file
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
var configuration: String? { get }
|
var configuration: ModelConfiguration { get }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The options dictionary for the `NSPersistentStore`
|
The options dictionary for the `NSPersistentStore`
|
||||||
@@ -106,10 +106,10 @@ public protocol CSLocalStorage: CSStorageInterface {
|
|||||||
var fileURL: URL { get }
|
var fileURL: URL { get }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The `NSBundle`s from which to search mapping models for migrations
|
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
var mappingModelBundles: [Bundle] { get }
|
var migrationMappingProviders: [Any] { get }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Options that tell the `CSDataStack` how to setup the persistent store
|
Options that tell the `CSDataStack` how to setup the persistent store
|
||||||
@@ -121,5 +121,5 @@ public protocol CSLocalStorage: CSStorageInterface {
|
|||||||
Called by the `CSDataStack` 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)
|
Called by the `CSDataStack` 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)
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
func eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool
|
func cs_eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool
|
||||||
}
|
}
|
||||||
+39
-27
@@ -35,37 +35,22 @@ import CoreData
|
|||||||
- SeeAlso: `SynchronousDataTransaction`
|
- SeeAlso: `SynchronousDataTransaction`
|
||||||
*/
|
*/
|
||||||
@objc
|
@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 `-commitAndWait` method was already called once.
|
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWaitWithError:` method was already called once.
|
||||||
|
|
||||||
- returns: a `CSSaveResult` containing the success or failure information
|
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
|
||||||
|
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func commitAndWait() -> CSSaveResult {
|
public func commitAndWait(error: NSErrorPointer) -> Bool {
|
||||||
|
|
||||||
return bridge {
|
return bridge(error) {
|
||||||
|
|
||||||
self.bridgeToSwift.commitAndWait()
|
if case (_, let error?) = self.bridgeToSwift.context.saveSynchronously(waitForMerge: true) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
throw error
|
||||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitAndWait` method was already called once.
|
|
||||||
|
|
||||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
|
||||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
|
||||||
*/
|
|
||||||
@objc
|
|
||||||
@discardableResult
|
|
||||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
|
||||||
|
|
||||||
return bridge {
|
|
||||||
|
|
||||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
|
||||||
|
|
||||||
closure(transaction.bridgeToObjectiveC)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,9 +129,9 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
|||||||
|
|
||||||
public typealias SwiftType = SynchronousDataTransaction
|
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) {
|
public required init(_ swiftValue: SynchronousDataTransaction) {
|
||||||
@@ -154,9 +139,36 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
|||||||
super.init(swiftValue as BaseDataTransaction)
|
super.init(swiftValue as BaseDataTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public required init(_ swiftValue: BaseDataTransaction) {
|
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||||
|
|
||||||
super.init(swiftValue as! SynchronousDataTransaction)
|
super.init(swiftValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -[CSSynchronousDataTransaction commitAndWaitWithError:] method")
|
||||||
|
@objc
|
||||||
|
public func commitAndWait() -> CSSaveResult {
|
||||||
|
|
||||||
|
return bridge {
|
||||||
|
|
||||||
|
self.bridgeToSwift.commitAndWait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Secondary tasks spawned from CSAsynchronousDataTransactions and CSSynchronousDataTransactions are no longer supported. ")
|
||||||
|
@objc
|
||||||
|
@discardableResult
|
||||||
|
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||||
|
|
||||||
|
return bridge {
|
||||||
|
|
||||||
|
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||||
|
|
||||||
|
closure(transaction.bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// CSUnsafeDataModelSchema.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: - CSUnsafeDataModelSchema
|
||||||
|
|
||||||
|
/**
|
||||||
|
The `CSUnsafeDataModelSchema` serves as the Objective-C bridging type for `UnsafeDataModelSchema`.
|
||||||
|
|
||||||
|
- SeeAlso: `UnsafeDataModelSchema`
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
public final class CSUnsafeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `CSUnsafeDataModelSchema` from an `NSManagedObjectModel`.
|
||||||
|
|
||||||
|
- parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension)
|
||||||
|
- parameter model: the `NSManagedObjectModel`
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
|
||||||
|
|
||||||
|
self.bridgeToSwift = UnsafeDataModelSchema(
|
||||||
|
modelName: modelName,
|
||||||
|
model: model
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: NSObject
|
||||||
|
|
||||||
|
public override var hash: Int {
|
||||||
|
|
||||||
|
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func isEqual(_ object: Any?) -> Bool {
|
||||||
|
|
||||||
|
guard let object = object as? CSUnsafeDataModelSchema else {
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return self.bridgeToSwift === object.bridgeToSwift
|
||||||
|
}
|
||||||
|
|
||||||
|
public override var description: String {
|
||||||
|
|
||||||
|
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CSDynamicSchema
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public var modelVersion: ModelVersion {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.modelVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public func rawModel() -> NSManagedObjectModel {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.rawModel()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
|
public let bridgeToSwift: UnsafeDataModelSchema
|
||||||
|
|
||||||
|
public required init(_ swiftValue: UnsafeDataModelSchema) {
|
||||||
|
|
||||||
|
self.bridgeToSwift = swiftValue
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - UnsafeDataModelSchema
|
||||||
|
|
||||||
|
extension UnsafeDataModelSchema: CoreStoreSwiftType {
|
||||||
|
|
||||||
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
|
public var bridgeToObjectiveC: CSUnsafeDataModelSchema {
|
||||||
|
|
||||||
|
return CSUnsafeDataModelSchema(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
+76
-16
@@ -35,33 +35,48 @@ import CoreData
|
|||||||
- SeeAlso: `UnsafeDataTransaction`
|
- SeeAlso: `UnsafeDataTransaction`
|
||||||
*/
|
*/
|
||||||
@objc
|
@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.
|
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.
|
||||||
|
|
||||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
|
- parameter success: the block executed if the save succeeds.
|
||||||
|
- parameter failure: the block executed if the save fails. A `CSError` is reported as the argument of the block.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func commit(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
public func commitWithSuccess(_ success: (() -> Void)?, _ failure: ((CSError) -> Void)?) {
|
||||||
|
|
||||||
self.bridgeToSwift.commit { (result) in
|
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (_, error) in
|
||||||
|
|
||||||
completion?(result.bridgeToObjectiveC)
|
defer {
|
||||||
|
|
||||||
|
withExtendedLifetime(self, {})
|
||||||
|
}
|
||||||
|
if let error = error {
|
||||||
|
|
||||||
|
failure?(error.bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
success?()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Saves the transaction changes and waits for completion synchronously. 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.
|
Saves the transaction changes and waits for completion synchronously. 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.
|
||||||
|
|
||||||
- returns: a `CSSaveResult` containing the success or failure information
|
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
|
||||||
|
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func commitAndWait() -> CSSaveResult {
|
public func commitAndWait(error: NSErrorPointer) -> Bool {
|
||||||
|
|
||||||
return bridge {
|
return bridge(error) {
|
||||||
|
|
||||||
self.bridgeToSwift.commitAndWait()
|
if case (_, let error?) = self.bridgeToSwift.context.saveSynchronously(waitForMerge: true) {
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +122,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
|||||||
Flushes all pending changes to the transaction's observers at the end of the `closure`'s execution. This is useful in conjunction with `ListMonitor`s and `ObjectMonitor`s created from `UnsafeDataTransaction`s used to manage temporary "scratch" data.
|
Flushes all pending changes to the transaction's observers at the end of the `closure`'s execution. This is useful in conjunction with `ListMonitor`s and `ObjectMonitor`s created from `UnsafeDataTransaction`s used to manage temporary "scratch" data.
|
||||||
|
|
||||||
- Important: Note that unlike `commit()`, `flush()` does not propagate/save updates to the `DataStack` and the persistent store. However, the flushed changes will be seen by children transactions created further from the current transaction (i.e. through `transaction.beginUnsafe()`)
|
- Important: Note that unlike `commit()`, `flush()` does not propagate/save updates to the `DataStack` and the persistent store. However, the flushed changes will be seen by children transactions created further from the current transaction (i.e. through `transaction.beginUnsafe()`)
|
||||||
- parameter closure: the closure where changes can be made prior to the flush
|
- parameter block: the block where changes can be made prior to the flush
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public func flush(_ block: () -> Void) {
|
public func flush(_ block: () -> Void) {
|
||||||
@@ -156,7 +171,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
|||||||
- that all saves will be done either through the `CSUnsafeDataTransaction`'s `-commit:` or `-commitAndWait` method, or by calling `-save:` manually on the context, its parent, and all other ancestor contexts if there are any.
|
- that all saves will be done either through the `CSUnsafeDataTransaction`'s `-commit:` or `-commitAndWait` method, or by calling `-save:` manually on the context, its parent, and all other ancestor contexts if there are any.
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public var internalContext: NSManagedObjectContext {
|
public func unsafeContext() -> NSManagedObjectContext {
|
||||||
|
|
||||||
return self.bridgeToSwift.context
|
return self.bridgeToSwift.context
|
||||||
}
|
}
|
||||||
@@ -174,9 +189,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
|||||||
|
|
||||||
public typealias SwiftType = UnsafeDataTransaction
|
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) {
|
public required init(_ swiftValue: UnsafeDataTransaction) {
|
||||||
@@ -184,9 +199,54 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
|||||||
super.init(swiftValue as BaseDataTransaction)
|
super.init(swiftValue as BaseDataTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public required init(_ swiftValue: BaseDataTransaction) {
|
public required override init(_ swiftValue: BaseDataTransaction) {
|
||||||
|
|
||||||
super.init(swiftValue as! UnsafeDataTransaction)
|
super.init(swiftValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Deprecated
|
||||||
|
|
||||||
|
@available(*, deprecated, renamed: "unsafeContext()")
|
||||||
|
@objc
|
||||||
|
public var internalContext: NSManagedObjectContext {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.context
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -[CSUnsafeDataTransaction commitWithSuccess:failure:] method")
|
||||||
|
@objc
|
||||||
|
public func commit(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
||||||
|
|
||||||
|
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (hasChanges, error) in
|
||||||
|
|
||||||
|
defer {
|
||||||
|
|
||||||
|
withExtendedLifetime(self, {})
|
||||||
|
}
|
||||||
|
if let error = error {
|
||||||
|
|
||||||
|
completion?(SaveResult(error).bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
completion?(SaveResult(hasChanges: hasChanges).bridgeToObjectiveC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new -[CSUnsafeDataTransaction commitAndWaitWithError:] method")
|
||||||
|
@objc
|
||||||
|
public func commitAndWait() -> CSSaveResult {
|
||||||
|
|
||||||
|
return bridge { () -> SaveResult in
|
||||||
|
|
||||||
|
switch self.bridgeToSwift.context.saveSynchronously(waitForMerge: true) {
|
||||||
|
|
||||||
|
case (let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
|
||||||
|
case (_, let error?): return SaveResult(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ import CoreData
|
|||||||
- SeeAlso: `Where`
|
- SeeAlso: `Where`
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause, CoreStoreObjectiveCType {
|
public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The internal `NSPredicate` instance for the `Where` clause
|
The internal `NSPredicate` instance for the `Where` clause
|
||||||
@@ -85,9 +85,11 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
|||||||
- parameter value: the arguments for the `==` operator
|
- parameter value: the arguments for the `==` operator
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(keyPath: KeyPath, isEqualTo value: NSObject?) {
|
public convenience init(keyPath: KeyPathString, isEqualTo value: CoreDataNativeType?) {
|
||||||
|
|
||||||
self.init(Where(keyPath, isEqualTo: value))
|
self.init(value == nil || value is NSNull
|
||||||
|
? Where("\(keyPath) == nil")
|
||||||
|
: Where("\(keyPath) == %@", value!))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,9 +99,9 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
|||||||
- parameter list: the array to check membership of
|
- parameter list: the array to check membership of
|
||||||
*/
|
*/
|
||||||
@objc
|
@objc
|
||||||
public convenience init(keyPath: KeyPath, isMemberOf list: [NSObject]) {
|
public convenience init(keyPath: KeyPathString, isMemberOf list: [CoreDataNativeType]) {
|
||||||
|
|
||||||
self.init(Where(keyPath, isMemberOf: list))
|
self.init(Where("\(keyPath) IN %@", list as NSArray))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,11 +149,11 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
|||||||
|
|
||||||
// MARK: CoreStoreObjectiveCType
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
public let bridgeToSwift: Where
|
public let bridgeToSwift: Where<NSManagedObject>
|
||||||
|
|
||||||
public init(_ swiftValue: Where) {
|
public init<D: NSManagedObject>(_ swiftValue: Where<D>) {
|
||||||
|
|
||||||
self.bridgeToSwift = swiftValue
|
self.bridgeToSwift = swiftValue.downcast()
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +161,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
|||||||
|
|
||||||
// MARK: - Where
|
// MARK: - Where
|
||||||
|
|
||||||
extension Where: CoreStoreSwiftType {
|
extension Where where D: NSManagedObject {
|
||||||
|
|
||||||
// MARK: CoreStoreSwiftType
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
@@ -167,4 +169,12 @@ extension Where: CoreStoreSwiftType {
|
|||||||
|
|
||||||
return CSWhere(self)
|
return CSWhere(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: FilePrivate
|
||||||
|
|
||||||
|
fileprivate func downcast() -> Where<NSManagedObject> {
|
||||||
|
|
||||||
|
return Where<NSManagedObject>(self.predicate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// CSXcodeDataModelSchema.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: - CSXcodeDataModelSchema
|
||||||
|
|
||||||
|
/**
|
||||||
|
The `CSXcodeDataModelSchema` serves as the Objective-C bridging type for `XcodeDataModelSchema`.
|
||||||
|
|
||||||
|
- SeeAlso: `XcodeDataModelSchema`
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes an `CSXcodeDataModelSchema` from an *.xcdatamodeld file URL.
|
||||||
|
|
||||||
|
- parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension)
|
||||||
|
- parameter modelVersionFileURL: the file URL that points to the .xcdatamodeld's "momd" file.
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
public required init(modelName: ModelVersion, modelVersionFileURL: URL) {
|
||||||
|
|
||||||
|
self.bridgeToSwift = XcodeDataModelSchema(
|
||||||
|
modelName: modelName,
|
||||||
|
modelVersionFileURL: modelVersionFileURL
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: NSObject
|
||||||
|
|
||||||
|
public override var hash: Int {
|
||||||
|
|
||||||
|
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func isEqual(_ object: Any?) -> Bool {
|
||||||
|
|
||||||
|
guard let object = object as? CSXcodeDataModelSchema else {
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return self.bridgeToSwift === object.bridgeToSwift
|
||||||
|
}
|
||||||
|
|
||||||
|
public override var description: String {
|
||||||
|
|
||||||
|
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CSDynamicSchema
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public var modelVersion: ModelVersion {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.modelVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public func rawModel() -> NSManagedObjectModel {
|
||||||
|
|
||||||
|
return self.bridgeToSwift.rawModel()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreObjectiveCType
|
||||||
|
|
||||||
|
public let bridgeToSwift: XcodeDataModelSchema
|
||||||
|
|
||||||
|
public required init(_ swiftValue: XcodeDataModelSchema) {
|
||||||
|
|
||||||
|
self.bridgeToSwift = swiftValue
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - XcodeDataModelSchema
|
||||||
|
|
||||||
|
extension XcodeDataModelSchema: CoreStoreSwiftType {
|
||||||
|
|
||||||
|
// MARK: CoreStoreSwiftType
|
||||||
|
|
||||||
|
public var bridgeToObjectiveC: CSXcodeDataModelSchema {
|
||||||
|
|
||||||
|
return CSXcodeDataModelSchema(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
//
|
||||||
|
// CoreDataNativeType.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: - CoreDataNativeType
|
||||||
|
|
||||||
|
/**
|
||||||
|
Objective-C Foundation types that are natively supported by Core Data managed attributes all conform to `CoreDataNativeType`.
|
||||||
|
*/
|
||||||
|
@objc
|
||||||
|
public protocol CoreDataNativeType: class, NSObjectProtocol {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSNumber
|
||||||
|
|
||||||
|
extension NSNumber: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSString
|
||||||
|
|
||||||
|
extension NSString: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSDate
|
||||||
|
|
||||||
|
extension NSDate: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSData
|
||||||
|
|
||||||
|
extension NSData: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSSet
|
||||||
|
|
||||||
|
extension NSSet: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSOrderedSet
|
||||||
|
|
||||||
|
extension NSOrderedSet: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSManagedObject
|
||||||
|
|
||||||
|
extension NSManagedObject: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSManagedObjectID
|
||||||
|
|
||||||
|
extension NSManagedObjectID: CoreDataNativeType {}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - NSNull
|
||||||
|
|
||||||
|
extension NSNull: CoreDataNativeType {}
|
||||||
+197
-36
@@ -48,8 +48,7 @@ extension AsynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDe
|
|||||||
("context", self.context),
|
("context", self.context),
|
||||||
("supportsUndo", self.supportsUndo),
|
("supportsUndo", self.supportsUndo),
|
||||||
("bypassesQueueing", self.bypassesQueueing),
|
("bypassesQueueing", self.bypassesQueueing),
|
||||||
("isCommitted", self.isCommitted),
|
("isCommitted", self.isCommitted)
|
||||||
("result", self.result as Any)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +141,13 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
|
|||||||
case .internalError(let NSError):
|
case .internalError(let NSError):
|
||||||
firstLine = ".internalError"
|
firstLine = ".internalError"
|
||||||
info.append(("NSError", NSError))
|
info.append(("NSError", NSError))
|
||||||
|
|
||||||
|
case .userError(error: let error):
|
||||||
|
firstLine = ".userError"
|
||||||
|
info.append(("Error", error))
|
||||||
|
|
||||||
|
case .userCancelled:
|
||||||
|
firstLine = ".userCancelled"
|
||||||
}
|
}
|
||||||
|
|
||||||
return createFormattedString(
|
return createFormattedString(
|
||||||
@@ -152,6 +158,32 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - CoreStoreSchema
|
||||||
|
|
||||||
|
extension CoreStoreSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
// MARK: CustomDebugStringConvertible
|
||||||
|
|
||||||
|
public var debugDescription: String {
|
||||||
|
|
||||||
|
return formattedDebugDescription(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreDebugStringConvertible
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return createFormattedString(
|
||||||
|
"(", ")",
|
||||||
|
("modelVersion", self.modelVersion),
|
||||||
|
("entitiesByConfiguration", self.entitiesByConfiguration),
|
||||||
|
("rawModel", self.rawModel())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - DataStack
|
// MARK: - DataStack
|
||||||
|
|
||||||
extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
@@ -173,14 +205,40 @@ extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertib
|
|||||||
("coordinator", self.coordinator),
|
("coordinator", self.coordinator),
|
||||||
("rootSavingContext", self.rootSavingContext),
|
("rootSavingContext", self.rootSavingContext),
|
||||||
("mainContext", self.mainContext),
|
("mainContext", self.mainContext),
|
||||||
("model", self.model),
|
("schemaHistory", self.schemaHistory),
|
||||||
("migrationChain", self.migrationChain),
|
|
||||||
("coordinator.persistentStores", self.coordinator.persistentStores)
|
("coordinator.persistentStores", self.coordinator.persistentStores)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Entity
|
||||||
|
|
||||||
|
extension Entity: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
// MARK: CustomDebugStringConvertible
|
||||||
|
|
||||||
|
public var debugDescription: String {
|
||||||
|
|
||||||
|
return formattedDebugDescription(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreDebugStringConvertible
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return createFormattedString(
|
||||||
|
"(", ")",
|
||||||
|
("type", self.type),
|
||||||
|
("entityName", self.entityName),
|
||||||
|
("isAbstract", self.isAbstract),
|
||||||
|
("versionHashModifier", self.versionHashModifier as Any)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - From
|
// MARK: - From
|
||||||
|
|
||||||
extension From: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension From: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
@@ -316,9 +374,9 @@ extension Into: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - LegacySQLiteStore
|
// MARK: - UnsafeDataModelSchema
|
||||||
|
|
||||||
extension LegacySQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension UnsafeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
// MARK: CustomDebugStringConvertible
|
// MARK: CustomDebugStringConvertible
|
||||||
|
|
||||||
@@ -334,20 +392,16 @@ extension LegacySQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringC
|
|||||||
|
|
||||||
return createFormattedString(
|
return createFormattedString(
|
||||||
"(", ")",
|
"(", ")",
|
||||||
("configuration", self.configuration as Any),
|
("modelVersion", self.modelVersion),
|
||||||
("storeOptions", self.storeOptions as Any),
|
("rawModel", self.rawModel())
|
||||||
("fileURL", self.fileURL),
|
|
||||||
("mappingModelBundles", self.mappingModelBundles),
|
|
||||||
("localStorageOptions", self.localStorageOptions)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - ListMonitor
|
// MARK: - ListMonitor
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertible {
|
private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
let sectionInfo: NSFetchedResultsSectionInfo
|
let sectionInfo: NSFetchedResultsSectionInfo
|
||||||
@@ -362,6 +416,7 @@ private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
extension ListMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension ListMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
// MARK: CustomDebugStringConvertible
|
// MARK: CustomDebugStringConvertible
|
||||||
@@ -384,7 +439,6 @@ extension ListMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvert
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: - LocalStorageOptions
|
// MARK: - LocalStorageOptions
|
||||||
@@ -451,7 +505,7 @@ extension MigrationChain: CustomDebugStringConvertible, CoreStoreDebugStringConv
|
|||||||
|
|
||||||
public var coreStoreDumpString: String {
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
guard self.valid else {
|
guard self.isValid else {
|
||||||
|
|
||||||
return "<invalid migration chain>"
|
return "<invalid migration chain>"
|
||||||
}
|
}
|
||||||
@@ -554,10 +608,9 @@ extension MigrationType: CustomDebugStringConvertible, CoreStoreDebugStringConve
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - ObjectMonitor
|
// MARK: - ObjectMonitor
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
// MARK: CustomDebugStringConvertible
|
// MARK: CustomDebugStringConvertible
|
||||||
@@ -579,7 +632,7 @@ extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConve
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// MARK: - OrderBy
|
// MARK: - OrderBy
|
||||||
|
|
||||||
@@ -607,6 +660,7 @@ extension OrderBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertible
|
|||||||
|
|
||||||
// MARK: - SaveResult
|
// MARK: - SaveResult
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use the new DataStack.perform(asynchronous:...) and DataStack.perform(synchronous:...) family of APIs")
|
||||||
extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
// MARK: CustomDebugStringConvertible
|
// MARK: CustomDebugStringConvertible
|
||||||
@@ -639,10 +693,9 @@ extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConverti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
|
|
||||||
// MARK: - SectionBy
|
// MARK: - SectionBy
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
extension SectionBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
extension SectionBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
// MARK: CustomDebugStringConvertible
|
// MARK: CustomDebugStringConvertible
|
||||||
@@ -663,7 +716,32 @@ extension SectionBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertib
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// MARK: - SchemaHistory
|
||||||
|
|
||||||
|
extension SchemaHistory: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
// MARK: CustomDebugStringConvertible
|
||||||
|
|
||||||
|
public var debugDescription: String {
|
||||||
|
|
||||||
|
return formattedDebugDescription(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreDebugStringConvertible
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return createFormattedString(
|
||||||
|
"(", ")",
|
||||||
|
("currentModelVersion", self.currentModelVersion),
|
||||||
|
("migrationChain", self.migrationChain),
|
||||||
|
("schemaByVersion", self.schemaByVersion)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Select
|
// MARK: - Select
|
||||||
@@ -789,8 +867,9 @@ extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvert
|
|||||||
("configuration", self.configuration as Any),
|
("configuration", self.configuration as Any),
|
||||||
("storeOptions", self.storeOptions as Any),
|
("storeOptions", self.storeOptions as Any),
|
||||||
("fileURL", self.fileURL),
|
("fileURL", self.fileURL),
|
||||||
("mappingModelBundles", self.mappingModelBundles),
|
("migrationMappingProviders", self.migrationMappingProviders),
|
||||||
("localStorageOptions", self.localStorageOptions)
|
("localStorageOptions", self.localStorageOptions),
|
||||||
|
("fileSize", self.fileSize() as Any)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -817,8 +896,7 @@ extension SynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDeb
|
|||||||
("context", self.context),
|
("context", self.context),
|
||||||
("supportsUndo", self.supportsUndo),
|
("supportsUndo", self.supportsUndo),
|
||||||
("bypassesQueueing", self.bypassesQueueing),
|
("bypassesQueueing", self.bypassesQueueing),
|
||||||
("isCommitted", self.isCommitted),
|
("isCommitted", self.isCommitted)
|
||||||
("result", self.result as Any)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -894,6 +972,80 @@ extension Where: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - VersionLock
|
||||||
|
|
||||||
|
extension VersionLock: CustomStringConvertible, CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
// MARK: CustomStringConvertible
|
||||||
|
|
||||||
|
public var description: String {
|
||||||
|
|
||||||
|
var string = "["
|
||||||
|
if self.hashesByEntityName.isEmpty {
|
||||||
|
|
||||||
|
string.append(":]")
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
for (index, keyValue) in self.hashesByEntityName.sorted(by: { $0.key < $1.key }).enumerated() {
|
||||||
|
|
||||||
|
let data = keyValue.value
|
||||||
|
let count = data.count
|
||||||
|
let bytes = data.withUnsafeBytes { (pointer: UnsafePointer<HashElement>) in
|
||||||
|
|
||||||
|
return (0 ..< (count / MemoryLayout<HashElement>.size))
|
||||||
|
.map({ "\("0x\(String(pointer[$0], radix: 16, uppercase: false))")" })
|
||||||
|
}
|
||||||
|
string.append("\(index == 0 ? "\n" : ",\n")\"\(keyValue.key)\": [\(bytes.joined(separator: ", "))]")
|
||||||
|
}
|
||||||
|
string.indent(1)
|
||||||
|
string.append("\n]")
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CustomDebugStringConvertible
|
||||||
|
|
||||||
|
public var debugDescription: String {
|
||||||
|
|
||||||
|
return formattedDebugDescription(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreDebugStringConvertible
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return self.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - XcodeDataModelSchema
|
||||||
|
|
||||||
|
extension XcodeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
// MARK: CustomDebugStringConvertible
|
||||||
|
|
||||||
|
public var debugDescription: String {
|
||||||
|
|
||||||
|
return formattedDebugDescription(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: CoreStoreDebugStringConvertible
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return createFormattedString(
|
||||||
|
"(", ")",
|
||||||
|
("modelVersion", self.modelVersion),
|
||||||
|
("modelVersionFileURL", self.modelVersionFileURL),
|
||||||
|
("rawModel", self.rawModel())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Private: Utilities
|
// MARK: - Private: Utilities
|
||||||
|
|
||||||
private typealias DumpInfo = [(key: String, value: Any)]
|
private typealias DumpInfo = [(key: String, value: Any)]
|
||||||
@@ -941,15 +1093,6 @@ fileprivate extension String {
|
|||||||
return String(repeating: " ", count: level * 4)
|
return String(repeating: " ", count: level * 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func trimSwiftModuleName() -> String {
|
|
||||||
|
|
||||||
if self.hasPrefix("Swift.") {
|
|
||||||
|
|
||||||
return self.substring(from: "Swift.".endIndex)
|
|
||||||
}
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate mutating func indent(_ level: Int) {
|
fileprivate mutating func indent(_ level: Int) {
|
||||||
|
|
||||||
self = self.replacingOccurrences(of: "\n", with: "\n\(String.indention(level))")
|
self = self.replacingOccurrences(of: "\n", with: "\n\(String.indention(level))")
|
||||||
@@ -970,7 +1113,7 @@ public protocol CoreStoreDebugStringConvertible {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Private:
|
// MARK: - Standard Types:
|
||||||
|
|
||||||
extension Array: CoreStoreDebugStringConvertible {
|
extension Array: CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
@@ -1063,6 +1206,8 @@ extension NSAttributeType: CoreStoreDebugStringConvertible {
|
|||||||
case .binaryDataAttributeType: return ".binaryDataAttributeType"
|
case .binaryDataAttributeType: return ".binaryDataAttributeType"
|
||||||
case .transformableAttributeType: return ".transformableAttributeType"
|
case .transformableAttributeType: return ".transformableAttributeType"
|
||||||
case .objectIDAttributeType: return ".objectIDAttributeType"
|
case .objectIDAttributeType: return ".objectIDAttributeType"
|
||||||
|
case .UUIDAttributeType: return ".UUIDAttributeType"
|
||||||
|
case .URIAttributeType: return ".URIAttributeType"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1212,7 +1357,15 @@ extension NSSortDescriptor: CoreStoreDebugStringConvertible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension URL: CoreStoreDebugStringConvertible {
|
extension NSString: CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return "\"\(self)\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NSURL: CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
public var coreStoreDumpString: String {
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
@@ -1247,3 +1400,11 @@ extension String: CoreStoreDebugStringConvertible {
|
|||||||
return "\"\(self)\""
|
return "\"\(self)\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension URL: CoreStoreDebugStringConvertible {
|
||||||
|
|
||||||
|
public var coreStoreDumpString: String {
|
||||||
|
|
||||||
|
return "\"\(self)\""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ public extension CoreStore {
|
|||||||
|
|
||||||
// MARK: Internal
|
// MARK: Internal
|
||||||
|
|
||||||
|
@inline(__always)
|
||||||
internal static func log(_ level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
internal static func log(_ level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||||
|
|
||||||
self.logger.log(
|
self.logger.log(
|
||||||
@@ -49,6 +50,7 @@ public extension CoreStore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inline(__always)
|
||||||
internal static func log(_ error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
internal static func log(_ error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||||
|
|
||||||
self.logger.log(
|
self.logger.log(
|
||||||
@@ -60,7 +62,8 @@ public extension CoreStore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
@inline(__always)
|
||||||
|
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||||
|
|
||||||
self.logger.assert(
|
self.logger.assert(
|
||||||
condition,
|
condition,
|
||||||
@@ -71,6 +74,7 @@ public extension CoreStore {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inline(__always)
|
||||||
internal static func abort(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) -> Never {
|
internal static func abort(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) -> Never {
|
||||||
|
|
||||||
self.logger.abort(
|
self.logger.abort(
|
||||||
@@ -31,27 +31,6 @@ import CoreData
|
|||||||
|
|
||||||
public extension CoreStore {
|
public extension CoreStore {
|
||||||
|
|
||||||
/**
|
|
||||||
Asynchronously adds a `StorageInterface` with default settings to the `defaultStack`. Migrations are also initiated by default.
|
|
||||||
```
|
|
||||||
CoreStore.addStorage(
|
|
||||||
InMemoryStore.self,
|
|
||||||
completion: { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let storage): // ...
|
|
||||||
case .failure(let error): // ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
```
|
|
||||||
- parameter storeType: the storage type
|
|
||||||
- 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>(_ storeType: T.Type, completion: @escaping (SetupResult<T>) -> Void) where T: DefaultInitializableStore {
|
|
||||||
|
|
||||||
self.defaultStack.addStorage(storeType.init(), completion: completion)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Asynchronously adds a `StorageInterface` to the `defaultStack`. Migrations are also initiated by default.
|
Asynchronously adds a `StorageInterface` to the `defaultStack`. Migrations are also initiated by default.
|
||||||
```
|
```
|
||||||
@@ -68,33 +47,11 @@ public extension CoreStore {
|
|||||||
- parameter storage: the storage
|
- 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.
|
- 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)
|
self.defaultStack.addStorage(storage, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Asynchronously adds a `LocalStorage` with default settings to the `defaultStack`. Migrations are also initiated by default.
|
|
||||||
```
|
|
||||||
let migrationProgress = CoreStore.addStorage(
|
|
||||||
SQLiteStore.self,
|
|
||||||
completion: { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let storage): // ...
|
|
||||||
case .failure(let error): // ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
```
|
|
||||||
- parameter storeType: the local storage type
|
|
||||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
|
||||||
- returns: a `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
|
|
||||||
*/
|
|
||||||
public static func addStorage<T: LocalStorage>(_ storeType: T.Type, completion: @escaping (SetupResult<T>) -> Void) -> Progress? where T: DefaultInitializableStore {
|
|
||||||
|
|
||||||
return self.defaultStack.addStorage(storeType.init(), completion: completion)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Asynchronously adds a `LocalStorage` to the `defaultStack`. Migrations are also initiated by default.
|
Asynchronously adds a `LocalStorage` to the `defaultStack`. Migrations are also initiated by default.
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
//
|
||||||
|
// CoreStore+Observing.swift
|
||||||
|
// CoreStore
|
||||||
|
//
|
||||||
|
// Copyright © 2015 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: - CoreStore
|
||||||
|
|
||||||
|
@available(OSX 10.12, *)
|
||||||
|
public extension CoreStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, creates an `ObjectMonitor` for the specified `DynamicObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `DynamicObject`.
|
||||||
|
|
||||||
|
- parameter object: the `DynamicObject` to observe changes from
|
||||||
|
- returns: a `ObjectMonitor` that monitors changes to `object`
|
||||||
|
*/
|
||||||
|
public static func monitorObject<D>(_ object: D) -> ObjectMonitor<D> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorObject(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||||
|
*/
|
||||||
|
public static func monitorList<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorList(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||||
|
*/
|
||||||
|
public static func monitorList<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorList(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let monitor = CoreStore.monitorList(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorList(clauseChain.from, clauseChain.fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||||
|
|
||||||
|
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||||
|
- 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<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ fetchClauses: FetchClause...) {
|
||||||
|
|
||||||
|
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||||
|
|
||||||
|
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||||
|
- 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<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ fetchClauses: [FetchClause]) {
|
||||||
|
|
||||||
|
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||||
|
|
||||||
|
```
|
||||||
|
CoreStore.monitorList(
|
||||||
|
{ (monitor) in
|
||||||
|
self.monitor = monitor
|
||||||
|
},
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||||
|
|
||||||
|
self.defaultStack.monitorList(
|
||||||
|
createAsynchronously: createAsynchronously,
|
||||||
|
clauseChain.from,
|
||||||
|
clauseChain.fetchClauses
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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.
|
||||||
|
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||||
|
*/
|
||||||
|
public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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.
|
||||||
|
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||||
|
*/
|
||||||
|
public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let monitor = CoreStore.monitorSectionedList(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.sectionBy(\.age, { "\($0!) years old" })
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||||
|
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||||
|
*/
|
||||||
|
public static func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||||
|
|
||||||
|
return self.defaultStack.monitorSectionedList(
|
||||||
|
clauseChain.from,
|
||||||
|
clauseChain.sectionBy,
|
||||||
|
clauseChain.fetchClauses
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||||
|
|
||||||
|
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
|
||||||
|
|
||||||
|
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||||
|
|
||||||
|
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
|
||||||
|
|
||||||
|
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
CoreStore.monitorSectionedList(
|
||||||
|
{ (monitor) in
|
||||||
|
self.monitor = monitor
|
||||||
|
},
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.sectionBy(\.age, { "\($0!) years old" })
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||||
|
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||||
|
*/
|
||||||
|
public static func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||||
|
|
||||||
|
self.defaultStack.monitorSectionedList(
|
||||||
|
createAsynchronously: createAsynchronously,
|
||||||
|
clauseChain.from,
|
||||||
|
clauseChain.sectionBy,
|
||||||
|
clauseChain.fetchClauses
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,389 @@
|
|||||||
|
//
|
||||||
|
// CoreStore+Querying.swift
|
||||||
|
// CoreStore
|
||||||
|
//
|
||||||
|
// Copyright © 2015 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: - CoreStore
|
||||||
|
|
||||||
|
public extension CoreStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `DynamicObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
|
||||||
|
|
||||||
|
- parameter object: a reference to the object created/fetched outside the `DataStack`
|
||||||
|
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||||
|
*/
|
||||||
|
public static func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchExisting(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `DynamicObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
|
||||||
|
|
||||||
|
- parameter objectID: the `NSManagedObjectID` for the object
|
||||||
|
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||||
|
*/
|
||||||
|
public static func fetchExisting<D: DynamicObject>(_ objectID: NSManagedObjectID) -> D? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchExisting(objectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `DynamicObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
|
||||||
|
|
||||||
|
- parameter objects: an array of `DynamicObject`s created/fetched outside the `DataStack`
|
||||||
|
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
|
||||||
|
*/
|
||||||
|
public static func fetchExisting<D: DynamicObject, S: Sequence>(_ objects: S) -> [D] where S.Iterator.Element == D {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchExisting(objects)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `DynamicObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
|
||||||
|
|
||||||
|
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||||
|
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
|
||||||
|
*/
|
||||||
|
public static func fetchExisting<D: DynamicObject, S: Sequence>(_ objectIDs: S) -> [D] where S.Iterator.Element == NSManagedObjectID {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchExisting(objectIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> D? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchOne(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> D? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchOne(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let youngestTeen = CoreStore.fetchOne(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) -> B.ObjectType? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchOne(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [D]? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchAll(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [D]? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchAll(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let people = CoreStore.fetchAll(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> [B.ObjectType]? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchAll(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> Int? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchCount(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchCount(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let numberOfAdults = CoreStore.fetchCount(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchCount(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchObjectID(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchObjectID(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let youngestTeenID = CoreStore.fetchObjectID(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) -> NSManagedObjectID? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchObjectID(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- 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<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||||
|
```
|
||||||
|
let idsOfAdults = transaction.fetchObjectIDs(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.where(\.age > 18)
|
||||||
|
.orderBy(.ascending(\.age))
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||||
|
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) -> [NSManagedObjectID]? {
|
||||||
|
|
||||||
|
return self.defaultStack.fetchObjectIDs(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) -> U? {
|
||||||
|
|
||||||
|
return self.defaultStack.queryValue(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) -> U? {
|
||||||
|
|
||||||
|
return self.defaultStack.queryValue(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
```
|
||||||
|
let averageAdultAge = CoreStore.queryValue(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.select(Int.self, .average(\.age))
|
||||||
|
.where(\.age > 18)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request.
|
||||||
|
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType {
|
||||||
|
|
||||||
|
return self.defaultStack.queryValue(clauseChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, queries a dictionary of attribtue values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||||
|
|
||||||
|
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Using the `defaultStack`, 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.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
|
||||||
|
- parameter from: a `From` clause indicating the entity type
|
||||||
|
- parameter selectClause: a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type.
|
||||||
|
- 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<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||||
|
|
||||||
|
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses.
|
||||||
|
|
||||||
|
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
|
||||||
|
```
|
||||||
|
let results = CoreStore.queryAttributes(
|
||||||
|
From<MyPersonEntity>()
|
||||||
|
.select(
|
||||||
|
NSDictionary.self,
|
||||||
|
.attribute(\.age, as: "age"),
|
||||||
|
.count(\.age, as: "numberOfPeople")
|
||||||
|
)
|
||||||
|
.groupBy(\.age)
|
||||||
|
)
|
||||||
|
for dictionary in results! {
|
||||||
|
let age = dictionary["age"] as! Int
|
||||||
|
let count = dictionary["numberOfPeople"] as! Int
|
||||||
|
print("There are \(count) people who are \(age) years old."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request.
|
||||||
|
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
|
||||||
|
*/
|
||||||
|
public static func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary {
|
||||||
|
|
||||||
|
return self.defaultStack.queryAttributes(clauseChain)
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user