Compare commits

...

89 Commits
6.3.1 ... 7.0.3

Author SHA1 Message Date
John Estropia
f119a3adec add SPM installation instructions to README 2020-01-08 11:21:41 +09:00
John Estropia
c951cb87a3 version bump 2020-01-08 11:03:43 +09:00
John Estropia
08147806a0 explicit exclusion of objc files in package.swift 2020-01-08 11:01:22 +09:00
John Estropia
4beb11519e Deprecation of ObjectiveC shivs 2020-01-08 10:26:27 +09:00
John Estropia
b7ebda4487 Use generic collection types in ListSnapshot mutators 2020-01-05 02:37:42 +09:00
John Estropia
b4489301ac fix SPM spec 2019-12-23 11:53:46 +09:00
John Estropia
c025e5acc6 version bump 2019-12-23 10:11:26 +09:00
John Estropia
57745f36a8 Allow purging of datasource 2019-12-17 21:10:01 +09:00
John Estropia
eef1c99f11 Allow custom views to consume ListSnapshot diffable data 2019-12-17 19:45:53 +09:00
John Estropia
9a19919392 add utility to create ObjectPublisher directly from a DynamicObject using its own context 2019-12-02 12:21:06 +09:00
John Estropia
3e2d62fe67 missed public modifier 2019-12-02 11:53:23 +09:00
John Estropia
6f275eb63a add "updatedItemIdentifiers" utility to ListSnapshot 2019-12-02 10:52:36 +09:00
John Estropia
b12dba4d15 optimizations 2019-11-29 20:09:43 +09:00
John Estropia
4ee1b04523 Support for fetchOffset in ListPublisher, optimize slicing logic 2019-11-18 19:52:57 +09:00
John Estropia
b1decc9853 Force fetchLimit for ListPublisher and ListSnapshot 2019-11-14 20:34:48 +09:00
John Estropia
c2e4c033ef Merge pull request #348 from ntnmrndn/fixWarning
Fix warning
2019-11-05 19:11:51 +09:00
John Estropia
e12223df85 fix casting error 2019-10-29 20:37:08 +09:00
John Estropia
468922d5ed fix casting issues 2019-10-29 20:30:03 +09:00
John Estropia
6b9a4b480b minor 2019-10-29 20:18:14 +09:00
Antoine Marandon
81b482e28b Fix warning 2019-10-29 17:27:25 +09:00
John Estropia
c112a84c0a Add debugDescription implementation for new Publisher and Snapshot types 2019-10-28 19:31:02 +09:00
John Estropia
88ab0b5e15 provide direct conversion from DynamicObject to ObjectSnapshot 2019-10-28 12:03:17 +09:00
John Estropia
717cb75720 Add utility to fetch ObjectPublishers by ObjectID 2019-10-28 11:23:12 +09:00
John Estropia
998938490c Make ObjectPublishers even lighter by lazy-loading observers 2019-10-25 19:16:38 +09:00
John Estropia
f3beca8769 fix compiler error in testcases 2019-10-25 16:17:25 +09:00
John Estropia
4baeb6d922 Fix weak linking of SwiftUI in podspec 2019-10-25 14:35:04 +09:00
John Estropia
98d860aff6 Add unit tests for List and Object Publishers 2019-10-25 14:34:22 +09:00
John Estropia
11a9e3991c changed ListPublisher and ObjectPublisher factory method naming to match ListMonitor and ObjectMonitor naming 2019-10-25 12:43:39 +09:00
John Estropia
f380d9dc25 ObjectSnapshot: allow dynamicMember keyPaths from superclasses 2019-10-25 12:36:13 +09:00
John Estropia
d546ff154f Merge pull request #344 from timfraedrich/patch-1
small correction to documentation
2019-10-23 19:27:33 +09:00
John Estropia
f21597d332 Merge pull request #341 from dmatushkin/develop
Fix for build on iOS with Swift Package Manager
2019-10-23 19:27:01 +09:00
John Estropia
d971c3a2ac README bug 2019-10-22 17:24:54 +09:00
John Estropia
80166a42bb Unify generic labeling 2019-10-22 16:16:47 +09:00
John Estropia
3d8bdf1cf3 Remove references to OSAtomic to silence deprecation warnings 2019-10-22 11:48:09 +09:00
John Estropia
1ddce5aa8d Package.swift update 2019-10-21 22:39:54 +09:00
John Estropia
7a1600fac4 README ok for now 2019-10-21 21:34:45 +09:00
John Estropia
e4e664d8ce README update 2019-10-21 21:24:34 +09:00
John Estropia
145edd5a7d README update 2019-10-21 21:15:46 +09:00
John Estropia
f5fed063ee Docs update 2019-10-20 18:17:31 +09:00
John Estropia
a267395618 WIP: README 2019-10-19 22:17:25 +09:00
John Estropia
326b897b06 WIP: docs 2019-10-19 09:34:31 +09:00
John Estropia
0b18366ab1 Renamed LiveList to ListPublisher and LiveObject to ObjectPublisher. WIP: docs 2019-10-18 19:36:27 +09:00
John Estropia
ddf599ba85 WIP: documentation 2019-10-18 08:19:55 +09:00
John Estropia
6e3e540d0a Improve handling in LiveObject and ObjectSnapshot when objects are deleted 2019-10-17 19:27:03 +09:00
John Estropia
bd066f0cef delete unused files 2019-10-17 16:59:00 +09:00
John Estropia
9764f33086 update demo app 2019-10-17 12:32:47 +09:00
John Estropia
0c19c878c5 LiveList refetch 2019-10-17 11:39:29 +09:00
John Estropia
1b8e517b5a WIP: update demo app 2019-10-17 07:40:15 +09:00
John Estropia
2818a778a4 Revert ObjectMonitor to previous implementation 2019-10-16 19:20:11 +09:00
John Estropia
64a0264354 DiffableDataSource.CollectionView implementation 2019-10-16 14:01:25 +09:00
John Estropia
7932625644 Merge branch 'develop' into datasources 2019-10-16 10:16:13 +09:00
John Estropia
4619fbbec3 WIP: ObjectRepresentable 2019-10-16 08:22:03 +09:00
John Estropia
6b64eb7650 WIP: ObjectRepresentable utilities 2019-10-14 21:36:03 +09:00
John Estropia
f5a165d47d back-portable TableView DiffableDataSource 2019-10-13 11:45:30 +09:00
John Estropia
12c58e3955 improved caching in utility methods 2019-10-12 10:02:00 +09:00
John Estropia
5af0d17de4 remov stateIDs 2019-10-12 07:20:09 +09:00
John Estropia
81dfb8e3e5 WIP: editable datasources 2019-10-11 07:47:49 +09:00
John Estropia
d5114fc4bc WIP 2019-10-08 21:09:34 +09:00
John Estropia
693fc7fbbb Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2019-10-07 10:16:11 +09:00
John Estropia
b073b7e795 swiftUI support done for now 2019-10-06 23:37:04 +09:00
Tim Fraedrich
56d9719984 small correction to documentation
While using some code from the documentation that led to issues I noticed that some parts of it are not accurate anymore, so I corrected a few small things that came to my attention. Maybe it is worth having an even closer look though.
2019-10-04 14:19:14 +00:00
John Estropia
953c9723a8 (WIP) SwiftUI working demo for LiveList<D> 2019-10-04 19:12:32 +09:00
John Estropia
c5a996d5ed WIP: do not use yet 2019-10-04 08:43:04 +09:00
John Estropia
53a83d823e Merge branch 'develop' into datasources 2019-09-22 07:39:18 +09:00
dmatushkin
6d75dcbc32 Fix for build on iOS with Swift Package Manager 2019-09-15 14:57:20 +04:00
John Estropia
0345ee9c94 Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2019-09-14 01:40:37 -04:00
John Estropia
4016b5dc83 Merge pull request #331 from jagbryrmiginte/develop
Fixes #328 by specifying platform requirements in Package.swift
2019-09-14 01:34:35 -04:00
John Estropia
64b5e102aa Merge pull request #340 from pushp1989/develop
Added Support for Swift 5
2019-09-14 01:33:51 -04:00
Pushpendra
8e3c44c072 Added Support for Swift 5
Upgraded Xcode build version
Added missing reference of for different targets
2019-09-13 15:27:46 +05:30
John Estropia
12dc32f7e6 Merge branch 'develop' into datasources
# Conflicts:
#	CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift
#	CoreStoreTests/DynamicModelTests.swift
#	Sources/BaseDataTransaction+Importing.swift
#	Sources/CoreStoreObject.swift
#	Sources/CustomSchemaMappingProvider.swift
#	Sources/DynamicObject.swift
#	Sources/Functions.swift
#	Sources/ImportableUniqueObject.swift
#	Sources/NSManagedObjectContext+Querying.swift
2019-08-29 17:15:45 +09:00
John Estropia
b4c38caf1e Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2019-08-29 17:03:16 +09:00
John Estropia
266b1a9913 Deprecation of enum CoreStore, reorganize global symbols 2019-08-29 17:03:09 +09:00
John Estropia
1740d168c8 Merge branch 'develop' 2019-08-27 14:38:16 +09:00
John Estropia
d42b397090 version bump 2019-08-27 14:38:05 +09:00
John Estropia
058cc1915b fix optimization issues in release build 2019-08-27 14:21:33 +09:00
John Estropia
02d5bf85ae fix ListMonitor demo for iOS 13 2019-08-20 12:42:34 +09:00
jagbryrmiginte
f0dac2454c Bump SPM package description to 5.0 to resolve compiler error 2019-07-21 12:12:30 +02:00
jagbryrmiginte
d4deed0cf7 Specify minimum deployment target for Swift Package Manager, fixes Issue #328 2019-07-21 12:09:53 +02:00
John Estropia
79655ffde5 added ObjectSnapshot as foundation for datasources API 2019-07-10 08:11:42 +09:00
John Estropia
cf46b45e8e Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2019-07-09 22:53:33 +09:00
John Estropia
ed3d21db77 WIP: reorganization of keypath utilities (in prep for @propertyWrappers) 2019-07-09 14:50:23 +09:00
John Estropia
f16e3593c0 Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2019-07-06 23:00:20 +09:00
John Estropia
67bb9340c7 provide way to check if an object has updated properties 2019-07-05 19:07:25 +09:00
John Estropia
5d49bd79f2 Merge pull request #326 from cool8jay/patch-1
Update README code style.
2019-06-29 13:19:14 +09:00
John Estropia
9f397b4337 Prevent crashing when DataStack is deallocated ahead of ListMonitor and child objects 2019-06-10 18:34:15 +09:00
cool8jay
7508d150d6 Update code style.
Update code style.
2019-06-05 08:43:06 +08:00
John Estropia
239db8168d remove artifacts from Carthage 2019-05-19 01:51:46 +09:00
John Estropia
30ab4386bf Merge branch 'develop' 2019-04-27 17:51:12 +09:00
John Estropia
08053ccb15 change protocol inheritance from class to AnyObject (as per recent Swift recommendation) 2019-04-27 17:50:55 +09:00
211 changed files with 12658 additions and 4478 deletions

3
.gitignore vendored
View File

@@ -9,3 +9,6 @@ DerivedData
*.orig
build
Playground_macOS.playground/playground.xcworkspace/xcuserdata
.swiftpm/xcode/package.xcworkspace/xcuserdata
.swiftpm/xcode/xcuserdata
Playground_iOS.playground/playground.xcworkspace/xcuserdata

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>CoreStore.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>

View File

@@ -1,41 +0,0 @@
language: objective-c
osx_image: xcode10.2
sudo: false
git:
submodules: false
notifications:
email: false
env:
global:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
matrix:
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.14 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=12.0,name=iPhone XS" SCHEME="CoreStore iOS" SDK=iphonesimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=11.0.1,name=iPhone 8" SCHEME="CoreStore iOS" SDK=iphonesimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.3.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=4.0,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator5.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator5.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator5.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=12.0,name=Apple TV 4K" SCHEME="CoreStore tvOS" SDK=appletvsimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=11.0,name=Apple TV 4K (at 1080p)" SCHEME="CoreStore tvOS" SDK=appletvsimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator12.0 RUN_TESTS="YES" POD_LINT="NO"
before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document
- gem install xcpretty --no-rdoc --no-ri --no-document
- npm install ios-sim -g
- ios-sim start --devicetypeid "com.apple.CoreSimulator.SimDeviceType.iPhone-8, 11.0"
script:
- set -o pipefail
- xcodebuild -version
- xcodebuild -showsdks
- if [ $RUN_TESTS == "YES" ]; then
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
fi
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator12.0" -destination "OS=11.0.1,name=iPhone 8" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator12.0" -destination "OS=11.0.1,name=iPhone 8" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
- if [ $POD_LINT == "YES" ]; then
pod lib lint --quick;
fi

View File

View File

View File

@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "CoreStore"
s.version = "6.3.1"
s.swift_version = "5.0"
s.version = "7.0.3"
s.swift_version = "5.1"
s.license = "MIT"
s.homepage = "https://github.com/JohnEstropia/CoreStore"
s.documentation_url = "https://JohnEstropia.github.io/CoreStore"
@@ -18,5 +18,5 @@ Pod::Spec.new do |s|
s.public_header_files = "Sources/**/*.h"
s.frameworks = "Foundation", "CoreData"
s.requires_arc = true
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG' }
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG', 'OTHER_LDFLAGS' => '-weak_framework Combine -weak_framework SwiftUI' }
end

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD1731BE1F8CC00949AFE"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -39,17 +48,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD1731BE1F8CC00949AFE"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -41,18 +41,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -69,6 +57,18 @@
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -95,8 +95,6 @@
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -27,6 +27,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "82BA18881C4BBCBA00A0916E"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore tvOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -39,17 +48,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "82BA18881C4BBCBA00A0916E"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore tvOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -29,8 +29,6 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -51,8 +49,6 @@
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -7,6 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
B50132242344E24300FC238B /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132232344E24300FC238B /* SwiftUIView.swift */; };
B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */; };
B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323423477D2300FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */; };
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */; };
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
@@ -23,6 +26,8 @@
B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; };
B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */; };
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */; };
B5635D192357F9F700B80E6B /* CollectionViewDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */; };
B5635D1B2357FA4B00B80E6B /* PaletteCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */; };
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; };
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3311B11DF3200F4F0C6 /* UserAccount.swift */; };
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */; };
@@ -34,6 +39,8 @@
B569651A1B30888A0075EE4A /* FetchingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */; };
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */; };
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */; };
B5AA37EF2357D30300FFD4B9 /* ColorsDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */; };
B5C37EE52357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */; };
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */; };
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; };
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -59,6 +66,9 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
B50132232344E24300FC238B /* SwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIView.swift; sourceTree = "<group>"; };
B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIContainerViewController.swift; sourceTree = "<group>"; };
B501323423477D2300FC238B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListObserverDemoViewController.swift; sourceTree = "<group>"; };
B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverDemoViewController.swift; sourceTree = "<group>"; };
B503FADD1AFDC71700F90881 /* Palette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palette.swift; sourceTree = "<group>"; };
@@ -78,6 +88,8 @@
B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2ToV3MigrationPolicy.swift; sourceTree = "<group>"; };
B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewDemoViewController.swift; sourceTree = "<group>"; };
B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCollectionViewCell.swift; sourceTree = "<group>"; };
B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = "<group>"; };
B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = "<group>"; };
B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLoggerViewController.swift; sourceTree = "<group>"; };
@@ -89,7 +101,9 @@
B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchingResultsViewController.swift; sourceTree = "<group>"; };
B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryingResultsViewController.swift; sourceTree = "<group>"; };
B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemo.xcdatamodel; sourceTree = "<group>"; };
B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorsDemo.swift; sourceTree = "<group>"; };
B5BDC9211C202429008147CD /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCollectionSectionHeaderView.swift; sourceTree = "<group>"; };
B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OrganismTableViewCell.swift; path = "CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift"; sourceTree = SOURCE_ROOT; };
B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV2.xcdatamodel; sourceTree = "<group>"; };
B5EE25841B36E23C0000406B /* OrganismV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV1.swift; sourceTree = "<group>"; };
@@ -105,6 +119,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */,
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */,
B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */,
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */,
@@ -114,14 +129,27 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B50132222344E20B00FC238B /* SwiftUI Demo */ = {
isa = PBXGroup;
children = (
B50132232344E24300FC238B /* SwiftUIView.swift */,
B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */,
);
path = "SwiftUI Demo";
sourceTree = "<group>";
};
B503FADA1AFDC71700F90881 /* List and Object Observers Demo */ = {
isa = PBXGroup;
children = (
B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */,
B52977D81B120B80003D50A5 /* ObserversViewController.swift */,
B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */,
B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */,
B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */,
B503FADD1AFDC71700F90881 /* Palette.swift */,
B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */,
B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */,
B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */,
);
path = "List and Object Observers Demo";
sourceTree = "<group>";
@@ -138,6 +166,7 @@
B52977E21B120F90003D50A5 /* Frameworks */ = {
isa = PBXGroup;
children = (
B501323423477D2300FC238B /* SwiftUI.framework */,
B52977E01B120F8A003D50A5 /* CoreLocation.framework */,
B5BDC9211C202429008147CD /* CoreStore.framework */,
B52977DE1B120F83003D50A5 /* MapKit.framework */,
@@ -166,6 +195,7 @@
isa = PBXGroup;
children = (
B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */,
B50132222344E20B00FC238B /* SwiftUI Demo */,
B566E3271B117AE700F4F0C6 /* Stack Setup Demo */,
B503FADA1AFDC71700F90881 /* List and Object Observers Demo */,
B52977DB1B120F2C003D50A5 /* Transactions Demo */,
@@ -270,6 +300,7 @@
TargetAttributes = {
B54AAD481AF4D26E00848AE0 = {
CreatedOnToolsVersion = 6.3;
DevelopmentTeam = 2JT32EJ5BH;
LastSwiftMigration = 0900;
};
};
@@ -311,6 +342,7 @@
buildActionMask = 2147483647;
files = (
B56965181B2E20CC0075EE4A /* TimeZone.swift in Sources */,
B5C37EE52357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift in Sources */,
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */,
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */,
B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */,
@@ -322,6 +354,7 @@
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */,
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */,
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */,
B5635D192357F9F700B80E6B /* CollectionViewDemoViewController.swift in Sources */,
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */,
B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */,
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */,
@@ -332,10 +365,14 @@
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */,
B5635D1B2357FA4B00B80E6B /* PaletteCollectionViewCell.swift in Sources */,
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */,
B5AA37EF2357D30300FFD4B9 /* ColorsDemo.swift in Sources */,
B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */,
B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */,
B50132242344E24300FC238B /* SwiftUIView.swift in Sources */,
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */,
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */,
);
@@ -473,6 +510,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 2JT32EJ5BH;
INFOPLIST_FILE = CoreStoreDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
@@ -485,6 +523,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 2JT32EJ5BH;
INFOPLIST_FILE = CoreStoreDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;

View File

@@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" 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>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
<capability name="collection view cell content view" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<customFonts key="customFonts">
@@ -68,10 +67,10 @@
</view>
<prototypes>
<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="172" width="375" height="44"/>
<rect key="frame" x="0.0" y="178" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<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="375" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq">
@@ -121,15 +120,15 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<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">
<rect key="frame" x="0.0" y="324" width="375" height="343"/>
<rect key="frame" x="0.0" y="304" width="375" height="363"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" 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>
<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="375" height="44"/>
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<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="375" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OQf-Bd-Zze">
@@ -170,25 +169,25 @@
</connections>
</tableView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XKA-Ub-c2X">
<rect key="frame" x="0.0" y="64" width="375" height="260"/>
<rect key="frame" x="0.0" y="44" width="375" height="260"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i7U-bW-juB" customClass="UIButton">
<rect key="frame" x="0.0" y="0.0" width="375" height="260"/>
<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">
<rect key="frame" x="20" y="90.5" width="335" height="26.5"/>
<rect key="frame" x="20" y="93.5" width="335" height="26.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</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">
<rect key="frame" x="20" y="131.5" width="335" height="20.5"/>
<rect key="frame" x="20" y="134.5" width="335" height="20.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="335" height="29"/>
<rect key="frame" x="20" y="20" width="335" height="32"/>
<segments>
<segment title="First"/>
<segment title="Second"/>
@@ -200,7 +199,7 @@
</connections>
</segmentedControl>
<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="335" height="2"/>
<rect key="frame" x="20" y="71" width="335" height="2"/>
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="trackTintColor" red="1" green="1" blue="1" alpha="0.20000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
</progressView>
@@ -269,21 +268,21 @@
<tableViewSection id="wIP-Hn-YfF">
<cells>
<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="35" width="375" height="50"/>
<rect key="frame" x="0.0" y="10" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accounts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q3n-Df-v1t">
<rect key="frame" x="16" y="6" width="82" height="24"/>
<rect key="frame" x="16" y="7" width="82" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</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">
<rect key="frame" x="16" y="30" width="263.5" height="13.5"/>
<rect key="frame" x="16" y="31" width="263.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -296,21 +295,21 @@
</connections>
</tableViewCell>
<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="85" width="375" height="50"/>
<rect key="frame" x="0.0" y="60" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Colors" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vpt-cT-gMo">
<rect key="frame" x="16" y="6" width="56" height="24"/>
<rect key="frame" x="16" y="7" width="56" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</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">
<rect key="frame" x="16" y="30" width="260.5" height="13.5"/>
<rect key="frame" x="16" y="31" width="260.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -323,21 +322,21 @@
</connections>
</tableViewCell>
<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="135" width="375" height="50"/>
<rect key="frame" x="0.0" y="110" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Placemarks" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UbU-Kd-yrY">
<rect key="frame" x="16" y="6" width="100.5" height="24"/>
<rect key="frame" x="16" y="7" width="100.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="16" y="30" width="179" height="13.5"/>
<rect key="frame" x="16" y="31" width="179" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -350,21 +349,21 @@
</connections>
</tableViewCell>
<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="185" width="375" height="50"/>
<rect key="frame" x="0.0" y="160" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Time Zones" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="C8Y-0y-lEG">
<rect key="frame" x="16" y="6" width="101.5" height="24"/>
<rect key="frame" x="16" y="7" width="101.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="16" y="30" width="168.5" height="13.5"/>
<rect key="frame" x="16" y="31" width="168.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -377,21 +376,21 @@
</connections>
</tableViewCell>
<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="235" width="375" height="50"/>
<rect key="frame" x="0.0" y="210" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZfY-Aq-Ykq">
<rect key="frame" x="16" y="6" width="61" height="24"/>
<rect key="frame" x="16" y="7" width="61" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="16" y="30" width="159" height="13.5"/>
<rect key="frame" x="16" y="31" width="159" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -404,21 +403,21 @@
</connections>
</tableViewCell>
<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="285" width="375" height="50"/>
<rect key="frame" x="0.0" y="260" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Evolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hSG-mG-YBw">
<rect key="frame" x="16" y="6" width="78.5" height="24"/>
<rect key="frame" x="16" y="7" width="78.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="16" y="30" width="179.5" height="13.5"/>
<rect key="frame" x="16" y="31" width="179.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -430,6 +429,33 @@
<segue destination="iVv-Vc-nCL" kind="show" id="HbO-rU-Qfj"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="o2r-2N-Xda" detailTextLabel="2hh-MM-Oea" style="IBUITableViewCellStyleSubtitle" id="f25-dJ-AuT">
<rect key="frame" x="0.0" y="310" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="f25-dJ-AuT" id="86t-0w-JT9">
<rect key="frame" x="0.0" y="0.0" width="348" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="SwiftUI" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="o2r-2N-Xda">
<rect key="frame" x="16" y="7" width="60.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629840000001" green="0.1840757281" blue="0.245942995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Binding with SwiftUI and Combine" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2hh-MM-Oea">
<rect key="frame" x="16" y="31" width="178" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629840000001" green="0.1840757281" blue="0.245942995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="rhi-tx-cSW" kind="show" id="kb3-NX-Aao"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
@@ -444,6 +470,38 @@
</objects>
<point key="canvasLocation" x="2634" y="2013"/>
</scene>
<!--SwiftUI-->
<scene sceneID="Uiz-5a-tKq">
<objects>
<viewController id="rhi-tx-cSW" customClass="SwiftUIContainerViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="0Nq-lg-kDJ"/>
<viewControllerLayoutGuide type="bottom" id="72Q-TT-uXH"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="JvO-3D-U2t">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" text="Not supported on this device/OS version" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Z0H-X0-3xA">
<rect key="frame" x="36" y="274.5" width="303" height="118.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="33"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="Z0H-X0-3xA" firstAttribute="centerY" secondItem="JvO-3D-U2t" secondAttribute="centerY" id="8Hp-yB-ciV"/>
<constraint firstItem="Z0H-X0-3xA" firstAttribute="leading" secondItem="JvO-3D-U2t" secondAttribute="leadingMargin" constant="20" id="l7i-J0-oG5"/>
<constraint firstAttribute="trailingMargin" secondItem="Z0H-X0-3xA" secondAttribute="trailing" constant="20" id="mrq-pp-Q06"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="SwiftUI" id="gFf-uX-EUI"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="HSp-lA-NAM" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3694" y="4816"/>
</scene>
<!--Object Observer-->
<scene sceneID="Y7v-tc-8cX">
<objects>
@@ -453,18 +511,18 @@
<viewControllerLayoutGuide type="bottom" id="aI4-O3-OCi"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="w8K-eN-RvU">
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="311.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
<rect key="frame" x="16" y="69.5" width="343" height="70"/>
<rect key="frame" x="16" y="69.5" width="343" height="80"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
</constraints>
</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">
<rect key="frame" x="16" y="149.5" width="343" height="18"/>
<rect key="frame" x="16" y="159.5" width="343" height="18"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/>
</constraints>
@@ -473,37 +531,37 @@
<nil key="highlightedColor"/>
</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">
<rect key="frame" x="16" y="187.5" width="74" height="18"/>
<rect key="frame" x="16" y="197.5" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</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">
<rect key="frame" x="16" y="225.5" width="74" height="18"/>
<rect key="frame" x="16" y="235.5" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</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">
<rect key="frame" x="16" y="263.5" width="74" height="18"/>
<rect key="frame" x="16" y="273.5" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="359" translatesAutoresizingMaskIntoConstraints="NO" id="YQ6-fq-3Wb">
<rect key="frame" x="98" y="181.5" width="263" height="31"/>
<rect key="frame" x="98" y="191.5" width="263" height="31"/>
<connections>
<action selector="hueSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="9Hy-3h-llE"/>
</connections>
</slider>
<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="98" y="219.5" width="263" height="31"/>
<rect key="frame" x="98" y="229.5" width="263" height="31"/>
<connections>
<action selector="saturationSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="qtU-ua-ZTc"/>
</connections>
</slider>
<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="98" y="257.5" width="263" height="31"/>
<rect key="frame" x="98" y="267.5" width="263" height="31"/>
<connections>
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
</connections>
@@ -566,7 +624,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="49t-Sy-Rq7" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="5864" y="1324.5"/>
<point key="canvasLocation" x="6316" y="1267"/>
</scene>
<!--Colors-->
<scene sceneID="3lD-lX-hIc">
@@ -580,34 +638,55 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
<rect key="frame" x="0.0" y="64" width="375" height="301.5"/>
<connections>
<segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/>
</connections>
</containerView>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp">
<rect key="frame" x="0.0" y="365.5" width="375" height="301.5"/>
<connections>
<segue destination="sll-yo-mBc" kind="embed" id="AAl-HS-dq2"/>
</connections>
</containerView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="cce-yT-4dn">
<rect key="frame" x="0.0" y="44" width="375" height="623"/>
<subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
<rect key="frame" x="0.0" y="0.0" width="375" height="311.5"/>
<connections>
<segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/>
</connections>
</containerView>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp">
<rect key="frame" x="0.0" y="311.5" width="375" height="311.5"/>
<connections>
<segue destination="Rdw-NU-NaK" kind="embed" id="3Ob-Bj-yvz"/>
</connections>
</containerView>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<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 firstItem="L5f-tW-lXf" firstAttribute="height" secondItem="6So-f3-4Gp" secondAttribute="height" id="8XS-L3-hvN"/>
<constraint firstItem="LNL-mj-D7l" firstAttribute="top" secondItem="6So-f3-4Gp" secondAttribute="bottom" id="8wL-zm-wnt"/>
<constraint firstItem="L5f-tW-lXf" firstAttribute="leading" secondItem="6x3-vn-Egt" secondAttribute="leadingMargin" constant="-16" id="CbE-2f-7wk"/>
<constraint firstAttribute="trailingMargin" secondItem="L5f-tW-lXf" secondAttribute="trailing" constant="-16" id="dso-2g-fgA"/>
<constraint firstItem="6So-f3-4Gp" firstAttribute="leading" secondItem="6x3-vn-Egt" secondAttribute="leadingMargin" constant="-16" id="eXM-D3-NLv"/>
<constraint firstItem="L5f-tW-lXf" firstAttribute="top" secondItem="IML-3o-caw" secondAttribute="bottom" id="zJ5-sE-iJA"/>
<constraint firstAttribute="trailing" secondItem="cce-yT-4dn" secondAttribute="trailing" id="DE1-u6-1mr"/>
<constraint firstItem="LNL-mj-D7l" firstAttribute="top" secondItem="cce-yT-4dn" secondAttribute="bottom" id="WIZ-M3-bdr"/>
<constraint firstItem="cce-yT-4dn" firstAttribute="leading" secondItem="6x3-vn-Egt" secondAttribute="leading" id="ZiS-j0-ANp"/>
<constraint firstItem="cce-yT-4dn" firstAttribute="top" secondItem="IML-3o-caw" secondAttribute="bottom" id="zjs-CM-7r5"/>
</constraints>
</view>
<extendedEdge key="edgesForExtendedLayout" top="YES"/>
<navigationItem key="navigationItem" title="Colors" id="7Gd-Ad-Bzu"/>
<navigationItem key="navigationItem" title="Colors" id="7Gd-Ad-Bzu">
<rightBarButtonItems>
<barButtonItem title="▼" width="36" id="aPM-OC-EB8">
<connections>
<action selector="toggleBottomContainerView" destination="YOI-b7-Nxn" id="7fn-z6-pne"/>
</connections>
</barButtonItem>
<barButtonItem title="▲" width="36" id="6q3-Zk-A9p">
<connections>
<action selector="toggleTopContainerView" destination="YOI-b7-Nxn" id="APN-Kk-C3n"/>
</connections>
</barButtonItem>
</rightBarButtonItems>
</navigationItem>
<nil key="simulatedBottomBarMetrics"/>
<connections>
<outlet property="bottomContainerView" destination="6So-f3-4Gp" id="C7O-e2-k0l"/>
<outlet property="stackView" destination="cce-yT-4dn" id="r5B-BT-mUM"/>
<outlet property="toggleBottomBarButtonItem" destination="aPM-OC-EB8" id="kEV-gg-XOX"/>
<outlet property="toggleTopBarButtonItem" destination="6q3-Zk-A9p" id="usC-Zu-DQm"/>
<outlet property="topContainerView" destination="L5f-tW-lXf" id="DRV-mm-rBY"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="C9h-Ba-WoL" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
@@ -620,7 +699,7 @@
<tabBarItem key="tabBarItem" title="Demo" image="second" id="3iQ-I2-4LW"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="00L-5k-Eno">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -638,19 +717,19 @@
</objects>
<point key="canvasLocation" x="1822" y="2013"/>
</scene>
<!--List Observer-->
<!--ListPublisher-->
<scene sceneID="gkX-bd-Rel">
<objects>
<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">
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="311.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<prototypes>
<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="22" width="375" height="44"/>
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF">
@@ -668,6 +747,7 @@
</label>
</subviews>
<constraints>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="HJC-5w-lIN" secondAttribute="trailing" id="8FZ-9e-AdN"/>
<constraint firstItem="HJC-5w-lIN" firstAttribute="height" secondItem="uQX-PI-UWF" secondAttribute="height" id="8Py-Ub-gQD"/>
<constraint firstItem="uQX-PI-UWF" firstAttribute="top" secondItem="aT8-nz-i5l" secondAttribute="topMargin" id="9e4-wD-lwf"/>
<constraint firstAttribute="centerY" secondItem="HJC-5w-lIN" secondAttribute="centerY" id="AeC-j4-DBE"/>
@@ -688,99 +768,14 @@
</connections>
</tableView>
<extendedEdge key="edgesForExtendedLayout" top="YES"/>
<navigationItem key="navigationItem" title="List Observer" id="JjF-x3-ixG"/>
<navigationItem key="navigationItem" title="ListPublisher" id="5kj-jr-HoL"/>
<connections>
<segue destination="dX3-kR-CYC" kind="show" identifier="ObjectObserverDemoViewController" id="hyN-De-zte"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="P5L-49-pOr" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="5085" y="1144.5"/>
</scene>
<!--List Observer-->
<scene sceneID="iDB-TD-It9">
<objects>
<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">
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<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="22" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<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="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH">
<rect key="frame" x="16" y="11" width="22" height="22"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" secondItem="5uq-Yi-XwH" secondAttribute="height" multiplier="1:1" id="oOe-HC-VyN"/>
</constraints>
</view>
<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="48" y="11" width="34.5" height="22"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="bottomMargin" secondItem="5uq-Yi-XwH" secondAttribute="bottom" id="2Bf-dJ-VmS"/>
<constraint firstItem="Zyu-PC-WmO" firstAttribute="leading" secondItem="5uq-Yi-XwH" secondAttribute="trailing" constant="10" id="6uD-S1-gkb"/>
<constraint firstAttribute="centerY" secondItem="Zyu-PC-WmO" secondAttribute="centerY" id="KQ6-bN-Og6"/>
<constraint firstItem="5uq-Yi-XwH" firstAttribute="top" secondItem="cHA-by-n4b" secondAttribute="topMargin" id="NqW-uA-mqj"/>
<constraint firstItem="Zyu-PC-WmO" firstAttribute="height" secondItem="5uq-Yi-XwH" secondAttribute="height" id="Yd5-bt-R8q"/>
<constraint firstItem="5uq-Yi-XwH" firstAttribute="leading" secondItem="cHA-by-n4b" secondAttribute="leadingMargin" id="a2a-Ol-0HV"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="colorView" destination="5uq-Yi-XwH" id="tgl-W1-A55"/>
<outlet property="label" destination="Zyu-PC-WmO" id="Oda-gD-ElI"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="lCE-i6-UCT" id="vTv-9f-P8U"/>
<outlet property="delegate" destination="lCE-i6-UCT" id="Ken-sI-O2f"/>
</connections>
</tableView>
<extendedEdge key="edgesForExtendedLayout" top="YES"/>
<navigationItem key="navigationItem" title="List Observer" id="koc-aK-cgD"/>
<connections>
<segue destination="dX3-kR-CYC" kind="show" identifier="ObjectObserverDemoViewController" id="fIB-GS-Ppk"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="QAS-su-ZdM" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="5085" y="1546"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="DTD-lH-nr5">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="sll-yo-mBc" sceneMemberID="viewController">
<extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="6XA-6M-yvZ">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" 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">
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</textAttributes>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="lCE-i6-UCT" kind="relationship" relationship="rootViewController" id="4Vz-ah-FHX"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="wJg-s1-Dpr" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="4404" y="1546"/>
<point key="canvasLocation" x="5156" y="1144"/>
</scene>
<!--Placemarks-->
<scene sceneID="LRD-q1-hw1">
@@ -791,11 +786,11 @@
<viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="k4s-iL-Krh">
<rect key="frame" x="0.0" y="0.0" width="375" height="603"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="623"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<mapView verifyAmbiguity="ignoreSizes" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
<rect key="frame" x="0.0" y="0.0" width="375" height="603"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="623"/>
<connections>
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
</connections>
@@ -832,14 +827,14 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<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="375" height="525"/>
<rect key="frame" x="0.0" y="125" width="375" height="542"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" 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"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<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="335" height="29"/>
<rect key="frame" x="20" y="74" width="335" height="32"/>
<segments>
<segment title="Log"/>
<segment title="Error"/>
@@ -887,8 +882,8 @@
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wJo-mp-1pS">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="0.68627450980392157" green="0.71372549019607845" blue="0.73333333333333328" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.12941176470588234" green="0.18431372549019609" blue="0.24705882352941178" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<textAttributes key="titleTextAttributes">
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -903,6 +898,80 @@
</objects>
<point key="canvasLocation" x="4404" y="1144.5"/>
</scene>
<!--ListPublisher-->
<scene sceneID="CXQ-vG-dtK">
<objects>
<collectionViewController id="EKY-1g-ALK" customClass="CollectionViewDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="hx3-j3-Q80">
<rect key="frame" x="0.0" y="0.0" width="375" height="311.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<collectionViewFlowLayout key="collectionViewLayout" automaticEstimatedItemSize="YES" minimumLineSpacing="10" minimumInteritemSpacing="10" id="X6n-f9-yEl">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="50" height="50"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="PaletteCollectionViewCell" id="x2U-Yq-KAx" customClass="PaletteCollectionViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="50" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="Alc-Is-Hc1">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NxF-xt-nas">
<rect key="frame" x="2" y="2" width="46" height="46"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
</view>
</subviews>
<constraints>
<constraint firstItem="NxF-xt-nas" firstAttribute="leading" secondItem="Alc-Is-Hc1" secondAttribute="leading" constant="2" id="Hjb-0k-4HP"/>
<constraint firstAttribute="trailing" secondItem="NxF-xt-nas" secondAttribute="trailing" constant="2" id="fKI-q8-bbI"/>
<constraint firstItem="NxF-xt-nas" firstAttribute="top" secondItem="Alc-Is-Hc1" secondAttribute="top" constant="2" id="qS6-eD-5T1"/>
<constraint firstAttribute="bottom" secondItem="NxF-xt-nas" secondAttribute="bottom" constant="2" id="uWP-o0-nzA"/>
</constraints>
</collectionViewCellContentView>
<connections>
<outlet property="colorView" destination="NxF-xt-nas" id="ywq-kB-ycp"/>
</connections>
</collectionViewCell>
</cells>
<collectionReusableView key="sectionHeaderView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="PaletteCollectionSectionHeaderView" id="bRa-K0-IUz" customClass="PaletteCollectionSectionHeaderView" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KHu-XO-jxd">
<rect key="frame" x="10" y="2" width="363" height="46"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="KHu-XO-jxd" secondAttribute="trailing" constant="2" id="Meb-ZG-6uP"/>
<constraint firstAttribute="bottom" secondItem="KHu-XO-jxd" secondAttribute="bottom" constant="2" id="SL5-cA-7nf"/>
<constraint firstItem="KHu-XO-jxd" firstAttribute="top" secondItem="bRa-K0-IUz" secondAttribute="top" constant="2" id="VFE-35-4gg"/>
<constraint firstItem="KHu-XO-jxd" firstAttribute="leading" secondItem="bRa-K0-IUz" secondAttribute="leading" constant="10" id="pzx-h0-rZd"/>
</constraints>
<connections>
<outlet property="label" destination="KHu-XO-jxd" id="qqK-Rm-eww"/>
</connections>
</collectionReusableView>
<connections>
<outlet property="dataSource" destination="EKY-1g-ALK" id="way-Q8-Xhb"/>
<outlet property="delegate" destination="EKY-1g-ALK" id="r9k-Fz-mWc"/>
</connections>
</collectionView>
<navigationItem key="navigationItem" title="ListPublisher" id="goy-Zu-94A"/>
<connections>
<segue destination="dX3-kR-CYC" kind="show" identifier="ObjectObserverDemoViewController" id="k4E-dJ-1lz"/>
</connections>
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Fmi-gN-RXz" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="5156" y="1484"/>
</scene>
<!--Time Zones-->
<scene sceneID="nFT-bo-7y9">
<objects>
@@ -916,7 +985,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<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">
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<rect key="frame" x="0.0" y="44" width="375" height="623"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" 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">
@@ -924,7 +993,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="YVj-dA-fyV">
<rect key="frame" x="20" y="26" width="335" height="29"/>
<rect key="frame" x="20" y="24.5" width="335" height="32"/>
<segments>
<segment title="Fetch"/>
<segment title="Query"/>
@@ -944,14 +1013,14 @@
</view>
<prototypes>
<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="375" height="44"/>
<rect key="frame" x="0.0" y="108" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<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="342" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="349" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<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="325" height="43.5"/>
<rect key="frame" x="15" y="0.0" width="326" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -998,21 +1067,21 @@
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<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="36" width="375" height="60"/>
<rect key="frame" x="0.0" y="28" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<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="375" height="59.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<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="16" y="11" width="48.5" height="24"/>
<rect key="frame" x="16" y="12" width="48.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="16" y="35" width="31" height="13.5"/>
<rect key="frame" x="16" y="36" width="31" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -1044,21 +1113,21 @@
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<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="36" width="375" height="60"/>
<rect key="frame" x="0.0" y="28" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<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="375" height="59.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<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="16" y="11" width="48.5" height="24"/>
<rect key="frame" x="16" y="12" width="48.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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="16" y="35" width="31" height="13.5"/>
<rect key="frame" x="16" y="36" width="31" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -1079,11 +1148,35 @@
</objects>
<point key="canvasLocation" x="4404" y="3055"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="s0N-is-CU8">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="Rdw-NU-NaK" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="clN-r9-yIR">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.68627450980000004" green="0.71372549019999998" blue="0.73333333329999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.12941176469999999" green="0.1840757281" blue="0.245942995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<textAttributes key="titleTextAttributes">
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="21"/>
<color key="textColor" red="0.68627450980000004" green="0.71372549019999998" blue="0.73333333329999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</textAttributes>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="EKY-1g-ALK" kind="relationship" relationship="rootViewController" id="CG7-LF-MHV"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="qAN-O1-Rn4" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="4404" y="1484"/>
</scene>
</scenes>
<resources>
<image name="second" width="30" height="30"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="fIB-GS-Ppk"/>
<segue reference="k4E-dJ-1lz"/>
</inferredMetricsTieBreakers>
</document>

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>6.3.1</string>
<string>6.3.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -50,5 +50,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
</dict>
</plist>

View File

@@ -0,0 +1,169 @@
//
// CollectionViewDemoViewController.swift
// CoreStoreDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - CollectionViewDemoViewController
final class CollectionViewDemoViewController: UICollectionViewController {
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem,
UIBarButtonItem(
barButtonSystemItem: .trash,
target: self,
action: #selector(self.resetBarButtonItemTouched(_:))
)
]
let filterBarButton = UIBarButtonItem(
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(self.addBarButtonItemTouched(_:))
),
UIBarButtonItem(
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.shuffleBarButtonItemTouched(_:))
),
filterBarButton
]
self.filterBarButton = filterBarButton
self.dataSource = DiffableDataSource.CollectionViewAdapter<Palette>(
collectionView: self.collectionView,
dataStack: ColorsDemo.stack,
cellProvider: { (collectionView, indexPath, palette) in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PaletteCollectionViewCell", for: indexPath) as! PaletteCollectionViewCell
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
},
supplementaryViewProvider: { (collectionView, kind, indexPath) in
switch kind {
case UICollectionView.elementKindSectionHeader:
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PaletteCollectionSectionHeaderView", for: indexPath) as! PaletteCollectionSectionHeaderView
view.label?.text = ColorsDemo.palettes.snapshot.sectionIDs[indexPath.section]
return view
default:
return nil
}
}
)
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
guard let self = self else {
return
}
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
}
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
destinationViewController.setPalette(palette)
default:
break
}
}
// MARK: UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes.snapshot[indexPath]
)
}
// MARK: Private
private var filterBarButton: UIBarButtonItem?
private var dataSource: DiffableDataSource.CollectionViewAdapter<Palette>?
deinit {
ColorsDemo.palettes.removeObserver(self)
}
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
try transaction.deleteAll(From<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
},
completion: { _ in }
)
}
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue()
palette.colorName .= nil
}
},
completion: { _ in }
)
}
}

View File

@@ -0,0 +1,88 @@
//
// ColorsDemo.swift
// CoreStoreDemo
//
// Created by John Rommel Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreStore
// MARK: - ColorsDemo
struct ColorsDemo {
enum Filter: String {
case all = "All Colors"
case light = "Light Colors"
case dark = "Dark Colors"
func next() -> Filter {
switch self {
case .all: return .light
case .light: return .dark
case .dark: return .all
}
}
func whereClause() -> Where<Palette> {
switch self {
case .all: return .init()
case .light: return (\Palette.brightness >= 0.9)
case .dark: return (\Palette.brightness <= 0.4)
}
}
}
static var filter = Filter.all {
didSet {
try! self.palettes.refetch(
From<Palette>()
.sectionBy(\.colorName)
.where(self.filter.whereClause())
.orderBy(.ascending(\.hue))
)
}
}
static let stack: DataStack = {
let dataStack = DataStack(
CoreStoreSchema(
modelVersion: "ColorsDemo",
entities: [
Entity<Palette>("Palette"),
],
versionLock: [
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
]
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
return dataStack
}()
static let palettes: ListPublisher<Palette> = {
return ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
)
}()
}

View File

@@ -10,89 +10,34 @@ import UIKit
import CoreStore
struct ColorsDemo {
enum Filter: String {
case all = "All Colors"
case light = "Light Colors"
case dark = "Dark Colors"
func next() -> Filter {
switch self {
case .all: return .light
case .light: return .dark
case .dark: return .all
}
}
func whereClause() -> Where<Palette> {
switch self {
case .all: return .init()
case .light: return (\Palette.brightness >= 0.9)
case .dark: return (\Palette.brightness <= 0.4)
}
}
}
static var filter = Filter.all {
didSet {
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> = {
try! ColorsDemo.stack.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
return ColorsDemo.stack.monitorSectionedList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
)
}()
}
// MARK: - ListObserverDemoViewController
class ListObserverDemoViewController: UITableViewController, ListSectionObserver {
// MARK: NSObject
deinit {
ColorsDemo.palettes.removeObserver(self)
final class ListObserverDemoViewController: UITableViewController {
// MARK: - EditableDataSource
final class EditableDataSource: DiffableDataSource.TableViewAdapter<Palette> {
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
let palette = ColorsDemo.palettes.snapshot[indexPath]
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.delete(palette)
},
completion: { _ in }
)
default:
break
}
}
}
// MARK: UIViewController
@@ -130,10 +75,28 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
filterBarButton
]
self.filterBarButton = filterBarButton
ColorsDemo.palettes.addObserver(self)
self.setTable(enabled: !ColorsDemo.palettes.isPendingRefetch)
self.dataSource = EditableDataSource(
tableView: self.tableView,
dataStack: ColorsDemo.stack,
cellProvider: { (tableView, indexPath, palette) in
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
}
)
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
guard let self = self else {
return
}
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
}
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
@@ -142,8 +105,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as Palette):
destinationViewController.palette = palette
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
destinationViewController.setPalette(palette)
default:
break
@@ -151,30 +114,6 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
}
// MARK: UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return ColorsDemo.palettes.numberOfSections()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ColorsDemo.palettes.numberOfObjects(in: section)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
let palette = ColorsDemo.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
@@ -183,105 +122,20 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes[indexPath]
sender: ColorsDemo.palettes.snapshot[indexPath]
)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
let palette = ColorsDemo.palettes[indexPath]
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.delete(palette)
},
completion: { _ in }
)
default:
break
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return ColorsDemo.palettes.sectionInfo(at: section).name
}
// MARK: ListObserver
func listMonitorWillChange(_ monitor: ListMonitor<Palette>) {
self.tableView.beginUpdates()
}
func listMonitorDidChange(_ monitor: ListMonitor<Palette>) {
self.tableView.endUpdates()
}
func listMonitorWillRefetch(_ monitor: ListMonitor<Palette>) {
self.setTable(enabled: false)
}
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.tableView.reloadData()
self.setTable(enabled: true)
}
// MARK: ListObjectObserver
func listMonitor(_ monitor: ListMonitor<Palette>, didInsertObject object: Palette, toIndexPath indexPath: IndexPath) {
self.tableView.insertRows(at: [indexPath], with: .automatic)
}
func listMonitor(_ monitor: ListMonitor<Palette>, didDeleteObject object: Palette, fromIndexPath indexPath: IndexPath) {
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
func listMonitor(_ monitor: ListMonitor<Palette>, didUpdateObject object: Palette, atIndexPath indexPath: IndexPath) {
if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell {
let palette = ColorsDemo.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
}
}
func listMonitor(_ monitor: ListMonitor<Palette>, didMoveObject object: Palette, fromIndexPath: IndexPath, toIndexPath: IndexPath) {
self.tableView.deleteRows(at: [fromIndexPath], with: .automatic)
self.tableView.insertRows(at: [toIndexPath], with: .automatic)
}
// MARK: ListSectionObserver
func listMonitor(_ monitor: ListMonitor<Palette>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) {
self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .automatic)
}
func listMonitor(_ monitor: ListMonitor<Palette>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .automatic)
}
// MARK: Private
private var filterBarButton: UIBarButtonItem?
private var dataSource: DiffableDataSource.TableViewAdapter<Palette>?
deinit {
ColorsDemo.palettes.removeObserver(self)
}
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
@@ -312,8 +166,6 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
}
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
self.setTable(enabled: false)
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
@@ -323,28 +175,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
palette.colorName .= nil
}
},
completion: { _ in
self.setTable(enabled: true)
}
)
}
private func setTable(enabled: Bool) {
tableView.isUserInteractionEnabled = enabled
UIView.animate(
withDuration: 0.2,
delay: 0,
options: .beginFromCurrentState,
animations: { () -> Void in
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
}
},
completion: nil
completion: { _ in }
)
}
}

View File

@@ -14,30 +14,23 @@ import CoreStore
class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
var palette: Palette? {
func setPalette<O: ObjectRepresentation>(_ newValue: O?) where O.ObjectType == Palette {
get {
guard self.monitor?.object?.objectID() != newValue?.objectID() else {
return self.monitor?.object
return
}
set {
if let newValue = newValue {
guard self.monitor?.object != newValue else {
return
}
self.monitor = newValue.asReadOnly(in: ColorsDemo.stack).map(ColorsDemo.stack.monitorObject(_:))
}
else {
if let palette = newValue {
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
else {
self.monitor = nil
}
self.monitor = nil
}
}
// MARK: NSObject
deinit {

View File

@@ -27,4 +27,33 @@ class ObserversViewController: UIViewController {
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: Private
@IBOutlet private dynamic weak var toggleTopBarButtonItem: UIBarButtonItem?
@IBOutlet private dynamic weak var toggleBottomBarButtonItem: UIBarButtonItem?
@IBOutlet private dynamic weak var stackView: UIStackView?
@IBOutlet private dynamic weak var topContainerView: UIView?
@IBOutlet private dynamic weak var bottomContainerView: UIView?
@IBAction private dynamic func toggleTopContainerView() {
UIView.animate(withDuration: 0.2) {
self.topContainerView!.isHidden.toggle()
}
self.toggleTopBarButtonItem!.isEnabled = !self.bottomContainerView!.isHidden
self.toggleBottomBarButtonItem!.isEnabled = !self.topContainerView!.isHidden
}
@IBAction private dynamic func toggleBottomContainerView() {
UIView.animate(withDuration: 0.2) {
self.bottomContainerView!.isHidden.toggle()
}
self.toggleTopBarButtonItem!.isEnabled = !self.bottomContainerView!.isHidden
self.toggleBottomBarButtonItem!.isEnabled = !self.topContainerView!.isHidden
}
}

View File

@@ -73,9 +73,12 @@ extension Palette {
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%"
}
}
extension Palette {
func setInitialValues(in transaction: BaseDataTransaction) {
self.hue .= Palette.randomHue()
self.saturation .= Float(1.0)
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0

View File

@@ -0,0 +1,17 @@
//
// PaletteCollectionSectionHeaderView.swift
// CoreStoreDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteCollectionSectionHeaderView
final class PaletteCollectionSectionHeaderView: UICollectionReusableView {
@IBOutlet weak var label: UILabel?
}

View File

@@ -0,0 +1,18 @@
//
// PaletteCollectionViewCell.swift
// CoreStoreDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteCollectionViewCell
final class PaletteCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var label: UILabel?
}

View File

@@ -8,7 +8,10 @@
import UIKit
class PaletteTableViewCell: UITableViewCell {
// MARK: - PaletteTableViewCell
final class PaletteTableViewCell: UITableViewCell {
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var label: UILabel?

View File

@@ -31,7 +31,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
super.viewDidAppear(animated)
CoreStore.logger = self
CoreStoreDefaults.logger = self
let alert = UIAlertController(
title: "Logger Demo",
@@ -46,7 +46,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
super.viewDidDisappear(animated)
CoreStore.logger = DefaultLogger()
CoreStoreDefaults.logger = DefaultLogger()
}

View File

@@ -8,7 +8,7 @@
import Foundation
protocol OrganismProtocol: class {
protocol OrganismProtocol: AnyObject {
var dna: Int64 { get set }

View File

@@ -0,0 +1,53 @@
//
// SwiftUIContainerViewController.swift
// CoreStoreDemo
//
// Created by John Rommel Estropia on 2019/10/02.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
#if canImport(SwiftUI)
import SwiftUI
#endif
#if canImport(Combine)
import Combine
#endif
import Compression
final class SwiftUIContainerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
#if canImport(SwiftUI) && canImport(Combine)
if #available(iOS 13, *) {
let hostingController = UIHostingController(
rootView: SwiftUIView(
palettes: ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
)
)
.environment(\.dataStack, ColorsDemo.stack)
)
self.addChild(hostingController)
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
hostingController.view.frame = self.view.bounds.inset(by: self.view.safeAreaInsets)
self.view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
}
#endif
}
}

View File

@@ -0,0 +1,184 @@
//
// SwiftUIView.swift
// CoreStoreDemo
//
// Created by John Rommel Estropia on 2019/10/02.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
#if canImport(SwiftUI) && canImport(Combine)
import SwiftUI
import Combine
import CoreStore
@available(iOS 13.0.0, *)
struct SwiftUIView: View {
@Environment(\.dataStack)
var dataStack: DataStack
@ObservedObject
var palettes: ListPublisher<Palette>
var body: some View {
NavigationView {
List {
ForEach(palettes.snapshot.sectionIDs, id: \.self) { (sectionID) in
Section(header: Text(sectionID)) {
ForEach(self.palettes.snapshot.items(inSectionWithID: sectionID), id: \.self) { palette in
NavigationLink(
destination: DetailView(palette: palette),
label: { ColorCell(palette: palette) }
)
}
.onDelete { itemIndices in
let objectIDsToDelete = self.palettes.snapshot.itemIDs(
inSectionWithID: sectionID,
atIndices: itemIndices
)
self.dataStack.perform(
asynchronous: { transaction in
transaction.delete(objectIDs: objectIDsToDelete)
},
completion: { _ in }
)
}
}
}
}
.navigationBarTitle(Text("SwiftUI (\(palettes.snapshot.numberOfItems) objects)"))
.navigationBarItems(
leading: EditButton(),
trailing: HStack {
Button(
action: {
self.dataStack.perform(
asynchronous: { transaction in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue()
palette.colorName .= nil
}
},
completion: { _ in }
)
},
label: {
Image(systemName: "goforward")
}
)
.frame(width: 30)
Button(
action: {
self.dataStack.perform(
asynchronous: { transaction in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
},
completion: { _ in }
)
},
label: {
Image(systemName: "plus")
}
)
.frame(width: 30)
}
)
.alert(
isPresented: $needsShowAlert,
content: {
Alert(
title: Text("SwiftUI Binding Demo"),
message: Text("This demo shows how to bind to ListPublisher and to CoreStoreObject when using SwiftUI"),
dismissButton: .cancel(Text("OK"))
)
}
)
.onAppear {
self.needsShowAlert = true
}
}
}
@State
private var needsShowAlert = false
}
@available(iOS 13.0.0, *)
struct ColorCell: View {
@ObservedObject
var palette: ObjectPublisher<Palette>
var body: some View {
HStack {
Color(palette.color ?? UIColor.clear)
.cornerRadius(5)
.frame(width: 30, height: 30, alignment: .leading)
Text(palette.colorText ?? "<Deleted>")
}
}
}
@available(iOS 13.0.0, *)
struct DetailView: View {
@Environment(\.dataStack)
var dataStack: DataStack
@ObservedObject
var palette: ObjectPublisher<Palette>
@State var hue: Float = 0
@State var saturation: Float = 0
@State var brightness: Float = 0
init(palette: ObjectPublisher<Palette>) {
self.palette = palette
self.hue = Float(palette.hue ?? 0)
self.saturation = palette.saturation ?? 0
self.brightness = palette.brightness ?? 0
}
var body: some View {
ZStack {
Color(palette.color ?? UIColor.clear)
.cornerRadius(20)
.padding(20)
VStack {
Text(palette.colorText ?? "<Deleted>")
.navigationBarTitle(Text("Color"))
Slider(value: $hue, in: 0.0 ... 359.0 as ClosedRange<Float>)
Slider(value: $saturation, in: 0.0 ... 1.0 as ClosedRange<Float>)
Slider(value: $brightness, in: 0.0 ... 0.1 as ClosedRange<Float>)
}
}
}
}
@available(iOS 13.0.0, *)
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView(
palettes: ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
)
)
.environment(\.dataStack, ColorsDemo.stack)
}
}
#endif

View File

@@ -15,10 +15,12 @@ import CoreStore
private struct Static {
static let dataStack = DataStack()
static let placeController: ObjectMonitor<Place> = {
try! CoreStore.addStorageAndWait(
try! Static.dataStack.addStorageAndWait(
SQLiteStore(
fileName: "PlaceDemo.sqlite",
configuration: "TransactionsDemo",
@@ -26,20 +28,20 @@ private struct Static {
)
)
var place = try! CoreStore.fetchOne(From<Place>())
var place = try! Static.dataStack.fetchOne(From<Place>())
if place == nil {
_ = try? CoreStore.perform(
_ = try? Static.dataStack.perform(
synchronous: { (transaction) in
let place = transaction.create(Into<Place>())
place.setInitialValues()
}
)
place = try! CoreStore.fetchOne(From<Place>())
place = try! Static.dataStack.fetchOne(From<Place>())
}
return CoreStore.monitorObject(place!)
return Static.dataStack.monitorObject(place!)
}()
}
@@ -170,7 +172,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
gesture.location(in: mapView),
toCoordinateFrom: mapView
)
CoreStore.perform(
Static.dataStack.perform(
asynchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object)
@@ -183,7 +185,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
@IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
_ = try? CoreStore.perform(
_ = try? Static.dataStack.perform(
synchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object)
@@ -194,7 +196,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
func geocode(place: Place) {
let transaction = CoreStore.beginUnsafe()
let transaction = Static.dataStack.beginUnsafe()
self.geocoder?.cancelGeocode()

View File

@@ -40,7 +40,7 @@ class BaseTestCase: XCTestCase {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
do {
@@ -50,7 +50,7 @@ class BaseTestCase: XCTestCase {
SQLiteStore(
fileURL: SQLiteStore.defaultRootDirectory
.appendingPathComponent(UUID().uuidString)
.appendingPathComponent("\(type(of: self))_\(($0 ?? "-null-")).sqlite"),
.appendingPathComponent("\(Self.self)_\(($0 ?? "-null-")).sqlite"),
configuration: $0,
localStorageOptions: .recreateStoreOnModelMismatch
)
@@ -67,11 +67,11 @@ class BaseTestCase: XCTestCase {
@nonobjc
func expectLogger<T>(_ expectations: [TestLogger.Expectation], closure: () throws -> T) rethrows -> T {
CoreStore.logger = TestLogger(self.prepareLoggerExpectations(expectations))
CoreStoreDefaults.logger = TestLogger(self.prepareLoggerExpectations(expectations))
defer {
self.checkExpectationsImmediately()
CoreStore.logger = TestLogger([:])
CoreStoreDefaults.logger = TestLogger([:])
}
return try closure()
}
@@ -79,17 +79,17 @@ class BaseTestCase: XCTestCase {
@nonobjc
func expectLogger(_ expectations: [TestLogger.Expectation: XCTestExpectation]) {
CoreStore.logger = TestLogger(expectations)
CoreStoreDefaults.logger = TestLogger(expectations)
}
@nonobjc
func expectError<T>(code: CoreStoreErrorCode, closure: () throws -> T) {
CoreStore.logger = TestLogger(self.prepareLoggerExpectations([.logError]))
CoreStoreDefaults.logger = TestLogger(self.prepareLoggerExpectations([.logError]))
defer {
self.checkExpectationsImmediately()
CoreStore.logger = TestLogger([:])
CoreStoreDefaults.logger = TestLogger([:])
}
do {
@@ -105,7 +105,7 @@ class BaseTestCase: XCTestCase {
}
catch {
XCTFail("Error not wrapped as \(cs_typeName(CoreStoreError.self)): \((error as NSError).coreStoreDumpString)")
XCTFail("Error not wrapped as \(Internals.typeName(CoreStoreError.self)): \((error as NSError).coreStoreDumpString)")
}
}
@@ -138,12 +138,12 @@ class BaseTestCase: XCTestCase {
super.setUp()
self.deleteStores()
CoreStore.logger = TestLogger([:])
CoreStoreDefaults.logger = TestLogger([:])
}
override func tearDown() {
CoreStore.logger = DefaultLogger()
CoreStoreDefaults.logger = DefaultLogger()
self.deleteStores()
super.tearDown()
}

View File

@@ -34,7 +34,7 @@ import CoreStore
class BaseTestDataTestCase: BaseTestCase {
@nonobjc
let dateFormatter: DateFormatter = cs_lazy {
let dateFormatter: DateFormatter = Internals.with {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")

View File

@@ -30,6 +30,10 @@
@import CoreData;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// MARK: - BridgingTests
@implementation BridgingTests
@@ -168,14 +172,8 @@
versionChain:nil];
XCTAssertNotNil(dataStack);
[CSCoreStore setDefaultStack:dataStack];
XCTAssertTrue([dataStack isEqual:[CSCoreStore defaultStack]]);
}
- (void)test_ThatStorages_BridgeCorrectly {
NSError *memoryError;
CSInMemoryStore *memoryStorage = [CSCoreStore
CSInMemoryStore *memoryStorage = [dataStack
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:&memoryError];
XCTAssertNotNil(memoryStorage);
@@ -186,7 +184,7 @@
XCTAssertNil(memoryError);
NSError *sqliteError;
CSSQLiteStore *sqliteStorage = [CSCoreStore
CSSQLiteStore *sqliteStorage = [dataStack
addSQLiteStorageAndWait:[CSSQLiteStore new]
error:&sqliteError];
XCTAssertNotNil(sqliteStorage);
@@ -208,18 +206,19 @@
}
- (void)test_ThatTransactions_BridgeCorrectly {
[CSCoreStore
setDefaultStack:[[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]];
[CSCoreStore
CSDataStack *dataStack = [[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil];
XCTAssertNotNil(dataStack);
[dataStack
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
{
CSUnsafeDataTransaction *transaction = [CSCoreStore beginUnsafe];
CSUnsafeDataTransaction *transaction = [dataStack beginUnsafe];
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
NSError *error;
@@ -230,23 +229,24 @@
{
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
NSError *error;
BOOL result = [CSCoreStore
BOOL result =
[dataStack
beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
NSError *error;
XCTAssertTrue([transaction commitAndWaitWithError:&error]);
XCTAssertNil(error);
[expectation fulfill];
}
error:&error];
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
NSError *error;
XCTAssertTrue([transaction commitAndWaitWithError:&error]);
XCTAssertNil(error);
[expectation fulfill];
}
error:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
[CSCoreStore beginAsynchronous:^(CSAsynchronousDataTransaction * _Nonnull transaction) {
[dataStack beginAsynchronous:^(CSAsynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
@@ -265,3 +265,5 @@
}
@end
#pragma clang diagnostic pop

View File

@@ -164,12 +164,73 @@ class DynamicModelTests: BaseTestDataTestCase {
animal.color .= .yellow
XCTAssertEqual(animal.color.value, Color.yellow)
for property in Animal.metaProperties(includeSuperclasses: true) {
switch property.keyPath {
case String(keyPath: \Animal.species):
XCTAssertTrue(property is ValueContainer<Animal>.Required<String>)
case String(keyPath: \Animal.master):
XCTAssertTrue(property is RelationshipContainer<Animal>.ToOne<Person>)
case String(keyPath: \Animal.color):
XCTAssertTrue(property is TransformableContainer<Animal>.Optional<Color>)
default:
XCTFail("Unknown KeyPath: \"\(property.keyPath)\"")
}
}
let dog = transaction.create(Into<Dog>())
XCTAssertEqual(dog.species.value, "Swift")
XCTAssertEqual(dog.nickname.value, nil)
XCTAssertEqual(dog.age.value, 1)
for property in Dog.metaProperties(includeSuperclasses: true) {
switch property.keyPath {
case String(keyPath: \Dog.species):
XCTAssertTrue(property is ValueContainer<Animal>.Required<String>)
case String(keyPath: \Dog.master):
XCTAssertTrue(property is RelationshipContainer<Animal>.ToOne<Person>)
case String(keyPath: \Dog.color):
XCTAssertTrue(property is TransformableContainer<Animal>.Optional<Color>)
case String(keyPath: \Dog.nickname):
XCTAssertTrue(property is ValueContainer<Dog>.Optional<String>)
case String(keyPath: \Dog.age):
XCTAssertTrue(property is ValueContainer<Dog>.Required<Int>)
case String(keyPath: \Dog.friends):
XCTAssertTrue(property is RelationshipContainer<Dog>.ToManyOrdered<Dog>)
case String(keyPath: \Dog.friendedBy):
XCTAssertTrue(property is RelationshipContainer<Dog>.ToManyUnordered<Dog>)
default:
XCTFail("Unknown KeyPath: \"\(property.keyPath)\"")
}
}
// #if swift(>=5.1)
//
// let dogKeyPathBuilder = Dog.keyPathBuilder()
// XCTAssertEqual(dogKeyPathBuilder.species.keyPathString, "SELF.species")
// XCTAssertEqual(dogKeyPathBuilder.master.title.keyPathString, "SELF.master.title")
// let a = dogKeyPathBuilder.master
// let b = dogKeyPathBuilder.master.spouse
// let c = dogKeyPathBuilder.master.spouse.pets
// let d = dogKeyPathBuilder.master.spouse.pets.color
// XCTAssertEqual(dogKeyPathBuilder.master.spouse.pets.color.keyPathString, "SELF.master.spouse.pets.color")
//
// #endif
let didSetObserver = dog.species.observe(options: [.new, .old]) { (object, change) in
XCTAssertEqual(object, dog)
@@ -213,7 +274,9 @@ class DynamicModelTests: BaseTestDataTestCase {
XCTAssertTrue(person.pets.value.isEmpty)
XCTAssertEqual(
cs_dynamicType(of: person.rawObject!).keyPathsForValuesAffectingValue(forKey: "displayName"),
person.rawObject!
.runtimeType()
.keyPathsForValuesAffectingValue(forKey: "displayName"),
["title", "name"]
)
@@ -229,9 +292,33 @@ class DynamicModelTests: BaseTestDataTestCase {
XCTAssertEqual(person.name.value, "John")
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
let personSnapshot1 = person.asSnapshot(in: transaction)!
XCTAssertEqual(person.name.value, personSnapshot1.name)
XCTAssertEqual(person.title.value, personSnapshot1.title)
XCTAssertEqual(person.displayName.value, personSnapshot1.displayName)
person.title .= "Sir"
XCTAssertEqual(person.displayName.value, "Sir John")
XCTAssertEqual(personSnapshot1.name, "John")
XCTAssertEqual(personSnapshot1.title, "Mr.")
XCTAssertEqual(personSnapshot1.displayName, "Mr. John")
let personSnapshot2 = person.asSnapshot(in: transaction)!
XCTAssertEqual(person.name.value, personSnapshot2.name)
XCTAssertEqual(person.title.value, personSnapshot2.title)
XCTAssertEqual(person.displayName.value, personSnapshot2.displayName)
var personSnapshot3 = personSnapshot2
personSnapshot3.name = "James"
XCTAssertEqual(personSnapshot1.name, "John")
XCTAssertEqual(personSnapshot1.displayName, "Mr. John")
XCTAssertEqual(personSnapshot2.name, "John")
XCTAssertEqual(personSnapshot2.displayName, "Sir John")
XCTAssertEqual(personSnapshot3.name, "James")
XCTAssertEqual(personSnapshot3.displayName, "Sir John")
person.pets.value.insert(dog)
XCTAssertEqual(person.pets.count, 1)
XCTAssertEqual(person.pets.value.first, dog)
@@ -337,7 +424,7 @@ class DynamicModelTests: BaseTestDataTestCase {
SQLiteStore(
fileURL: SQLiteStore.defaultRootDirectory
.appendingPathComponent(UUID().uuidString)
.appendingPathComponent("\(type(of: self))_\((configuration ?? "-null-")).sqlite"),
.appendingPathComponent("\(Self.self)_\((configuration ?? "-null-")).sqlite"),
configuration: configuration,
localStorageOptions: .recreateStoreOnModelMismatch
)

View File

@@ -31,6 +31,7 @@ import CoreStore
// MARK: - ErrorTests
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
final class ErrorTests: XCTestCase {
@objc
@@ -88,7 +89,7 @@ final class ErrorTests: XCTestCase {
let schemaHistory = SchemaHistory(
XcodeDataModelSchema.from(
modelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
)
let version = "1.0.0"

View File

@@ -74,7 +74,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
try from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.safeAffectedStores())
@@ -88,7 +88,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -113,7 +113,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -128,7 +128,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -143,7 +143,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config2")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -160,7 +160,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -177,7 +177,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -194,7 +194,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>("Config2")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -219,7 +219,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -234,7 +234,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -249,7 +249,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config2")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -266,7 +266,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -281,7 +281,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -298,7 +298,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>("Config2")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -323,7 +323,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -338,7 +338,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -353,7 +353,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>("Config2")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -370,7 +370,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>()
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)
@@ -385,7 +385,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>("Config1")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
self.expectError(code: .persistentStoreNotFound) {
try from.applyToFetchRequest(request, context: dataStack.mainContext)
@@ -402,7 +402,7 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity2>("Config2")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
let storesFound: Void? = try? from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertNotNil(storesFound)
XCTAssertNotNil(request.entity)

View File

@@ -68,7 +68,7 @@ final class GroupByTests: BaseTestCase {
let groupBy = GroupBy<NSManagedObject>(#keyPath(TestEntity1.testString))
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
try From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext)
groupBy.applyToFetchRequest(request)

View File

@@ -0,0 +1,304 @@
//
// ListPublisherTests.swift
// CoreStore iOS
//
// Copyright © 2018 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.
//
#if canImport(UIKit) || canImport(AppKit)
import XCTest
@testable
import CoreStore
// MARK: - ListPublisherTests
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
class ListPublisherTests: BaseTestDataTestCase {
@objc
dynamic func test_ThatListPublishers_CanReceiveInsertNotifications() {
self.prepareStack { (stack) in
let observer = NSObject()
let listPublisher = stack.publishList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
XCTAssertFalse(listPublisher.snapshot.hasSections())
XCTAssertFalse(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.itemIDs.isEmpty)
let didChangeExpectation = self.expectation(description: "didChange")
listPublisher.addObserver(observer) { listPublisher in
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 1)
didChangeExpectation.fulfill()
}
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
let object = transaction.create(Into<TestEntity1>())
object.testBoolean = NSNumber(value: true)
object.testNumber = NSNumber(value: 1)
object.testDecimal = NSDecimalNumber(string: "1")
object.testString = "nil:TestEntity1:1"
object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
withExtendedLifetime(listPublisher, {})
withExtendedLifetime(observer, {})
}
}
@objc
dynamic func test_ThatListPublishers_CanReceiveUpdateNotifications() {
self.prepareStack { (stack) in
self.prepareTestDataForStack(stack)
let observer = NSObject()
let listPublisher = stack.publishList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
let didChangeExpectation = self.expectation(description: "didChange")
listPublisher.addObserver(observer) { listPublisher in
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
didChangeExpectation.fulfill()
}
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
if let object = try transaction.fetchOne(
From<TestEntity1>(),
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
object.testNumber = NSNumber(value: 11)
object.testDecimal = NSDecimalNumber(string: "11")
object.testString = "nil:TestEntity1:11"
object.testData = ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!
}
else {
XCTFail()
}
if let object = try transaction.fetchOne(
From<TestEntity1>(),
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
object.testNumber = NSNumber(value: 22)
object.testDecimal = NSDecimalNumber(string: "22")
object.testString = "nil:TestEntity1:22"
object.testData = ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!
}
else {
XCTFail()
}
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
withExtendedLifetime(listPublisher, {})
withExtendedLifetime(observer, {})
}
}
@objc
dynamic func test_ThatListPublishers_CanReceiveMoveNotifications() {
self.prepareStack { (stack) in
self.prepareTestDataForStack(stack)
let observer = NSObject()
let listPublisher = stack.publishList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
let didChangeExpectation = self.expectation(description: "didChange")
listPublisher.addObserver(observer) { listPublisher in
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 1)
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 4)
didChangeExpectation.fulfill()
}
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
if let object = try transaction.fetchOne(
From<TestEntity1>(),
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
object.testBoolean = NSNumber(value: true)
}
else {
XCTFail()
}
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
withExtendedLifetime(listPublisher, {})
withExtendedLifetime(observer, {})
}
}
@objc
dynamic func test_ThatListPublishers_CanReceiveDeleteNotifications() {
self.prepareStack { (stack) in
self.prepareTestDataForStack(stack)
let observer = NSObject()
let listPublisher = stack.publishList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 2)
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 2)
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 1), 3)
let didChangeExpectation = self.expectation(description: "didChange")
listPublisher.addObserver(observer) { listPublisher in
XCTAssertTrue(listPublisher.snapshot.hasSections())
XCTAssertEqual(listPublisher.snapshot.numberOfSections, 1)
XCTAssertTrue(listPublisher.snapshot.hasItems())
XCTAssertTrue(listPublisher.snapshot.hasItems(inSectionIndex: 0))
XCTAssertEqual(listPublisher.snapshot.numberOfItems(inSectionIndex: 0), 3)
didChangeExpectation.fulfill()
}
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
let count = try transaction.deleteAll(
From<TestEntity1>(),
Where<TestEntity1>(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
)
XCTAssertEqual(count, 2)
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
}
}
}
#endif

View File

@@ -0,0 +1,154 @@
//
// ObjectPublisherTests.swift
// CoreStore
//
// Copyright © 2018 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
// MARK: - ObjectPublisherTests
@available(macOS 10.12, *)
class ObjectPublisherTests: BaseTestDataTestCase {
@objc
dynamic func test_ThatObjectPublishers_CanReceiveUpdateNotifications() {
self.prepareStack { (stack) in
self.prepareTestDataForStack(stack)
guard let object = try stack.fetchOne(
From<TestEntity1>(),
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
XCTFail()
return
}
let observer = NSObject()
let objectPublisher = stack.publishObject(object)
XCTAssertEqual(objectPublisher.object, object)
XCTAssertNotNil(objectPublisher.snapshot)
let didChangeExpectation = self.expectation(description: "didChange")
objectPublisher.addObserver(observer) { objectPublisher in
XCTAssertEqual(objectPublisher.object?.testNumber, NSNumber(value: 10))
XCTAssertEqual(objectPublisher.object?.testString, "nil:TestEntity1:10")
didChangeExpectation.fulfill()
}
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
XCTFail()
try transaction.cancel()
}
object.testNumber = NSNumber(value: 10)
object.testString = "nil:TestEntity1:10"
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
withExtendedLifetime(objectPublisher, {})
withExtendedLifetime(observer, {})
}
}
@objc
dynamic func test_ThatObjectPublishers_CanReceiveDeleteNotifications() {
self.prepareStack { (stack) in
self.prepareTestDataForStack(stack)
guard let object = try stack.fetchOne(
From<TestEntity1>(),
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
XCTFail()
return
}
let observer = NSObject()
let objectPublisher = stack.publishObject(object)
XCTAssertEqual(objectPublisher.object, object)
XCTAssertNotNil(objectPublisher.snapshot)
let didChangeExpectation = self.expectation(description: "didChange")
objectPublisher.addObserver(observer) { objectPublisher in
XCTAssertNil(objectPublisher.object)
XCTAssertNil(objectPublisher.snapshot)
didChangeExpectation.fulfill()
}
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
XCTFail()
try transaction.cancel()
}
transaction.delete(object)
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
withExtendedLifetime(objectPublisher, {})
withExtendedLifetime(observer, {})
}
}
}

View File

@@ -179,7 +179,7 @@ final class OrderByTests: XCTestCase {
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
let orderBy = OrderBy<NSManagedObject>(.ascending("key"))
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
orderBy.applyToFetchRequest(request)
XCTAssertNotNil(request.sortDescriptors)
XCTAssertEqual(request.sortDescriptors ?? [], orderBy.sortDescriptors)

View File

@@ -39,7 +39,7 @@ class SetupTests: BaseTestDataTestCase {
let schemaHistory = SchemaHistory(
XcodeDataModelSchema.from(
modelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
)
let stack = DataStack(schemaHistory: schemaHistory)
@@ -56,9 +56,6 @@ class SetupTests: BaseTestDataTestCase {
XCTAssertTrue(stack.schemaHistory.migrationChain.isEmpty)
XCTAssertTrue(stack.schemaHistory.migrationChain.rootVersions.isEmpty)
XCTAssertTrue(stack.schemaHistory.migrationChain.leafVersions.isEmpty)
CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack)
}
do {
@@ -68,15 +65,12 @@ class SetupTests: BaseTestDataTestCase {
DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)),
bundle: Bundle(for: Self.self),
migrationChain: migrationChain
)
}
XCTAssertEqual(stack.modelVersion, "Model")
XCTAssertEqual(stack.schemaHistory.migrationChain, migrationChain)
CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack)
}
}
@@ -85,7 +79,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
do {
@@ -140,7 +134,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
do {
@@ -208,7 +202,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
try! stack.addStorageAndWait(sqliteStore)
self.prepareTestDataForStack(stack)
@@ -227,7 +221,7 @@ class SetupTests: BaseTestDataTestCase {
let metadata = try createStore()
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
try sqliteStore.cs_eraseStorageAndWait(
metadata: metadata,
@@ -260,7 +254,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
do {
@@ -328,7 +322,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
try! stack.addStorageAndWait(
SQLiteStore.legacy(
@@ -354,7 +348,7 @@ class SetupTests: BaseTestDataTestCase {
let metadata = try createStore()
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
bundle: Bundle(for: Self.self)
)
try sqliteStore.cs_eraseStorageAndWait(
metadata: metadata,

View File

@@ -112,7 +112,7 @@ final class StorageInterfaceTests: XCTestCase {
.appendingPathExtension("db")
let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
mappingModelBundle: Bundle(for: Self.self)
)
let store = SQLiteStore(
@@ -150,7 +150,7 @@ final class StorageInterfaceTests: XCTestCase {
let fileName = UUID().uuidString + ".db"
let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
mappingModelBundle: Bundle(for: Self.self)
)
let store = SQLiteStore(
fileName: fileName,
@@ -236,7 +236,7 @@ final class StorageInterfaceTests: XCTestCase {
let fileName = UUID().uuidString + ".db"
let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
mappingModelBundle: Bundle(for: Self.self)
)
let store = SQLiteStore.legacy(
fileName: fileName,

View File

@@ -43,7 +43,7 @@ final class TweakTests: XCTestCase {
$0.fetchLimit = 200
$0.predicate = predicate
}
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
tweak.applyToFetchRequest(request)
XCTAssertEqual(request.fetchOffset, 100)
XCTAssertEqual(request.fetchLimit, 200)

View File

@@ -31,12 +31,12 @@ import CoreStore
// MARK: - XCTAssertAllEqual
private func XCTAssertAllEqual<D>(_ whereClauses: Where<D>...) {
private func XCTAssertAllEqual<O>(_ whereClauses: Where<O>...) {
XCTAssertAllEqual(whereClauses)
}
private func XCTAssertAllEqual<D>(_ whereClauses: [Where<D>]) {
private func XCTAssertAllEqual<O>(_ whereClauses: [Where<O>]) {
for i in whereClauses.indices {
@@ -47,6 +47,17 @@ private func XCTAssertAllEqual<D>(_ whereClauses: [Where<D>]) {
}
}
private func XCTAssertAllEqual<D: Equatable>(_ items: D...) {
for i in items.indices {
for j in items.indices where j != i {
XCTAssertEqual(items[i], items[j])
}
}
}
//MARK: - WhereTests
@@ -55,8 +66,8 @@ final class WhereTests: XCTestCase {
@objc
dynamic func test_ThatDynamicModelKeyPaths_CanBeCreated() {
XCTAssertEqual(String(keyPath: \TestEntity1.testEntityID), "testEntityID")
XCTAssertEqual(String(keyPath: \Animal.color), "color")
XCTAssertAllEqual(String(keyPath: \TestEntity1.testEntityID), "testEntityID")
XCTAssertAllEqual(String(keyPath: \Animal.color), "color")
}
@objc
@@ -66,17 +77,24 @@ final class WhereTests: XCTestCase {
do {
XCTAssertEqual(
// let keyPathBuilder = TestEntity1.keyPathBuilder()
// let kp = \TestEntity1.testToOne
// print(keyPathBuilder.testString)
// print(keyPathBuilder.testToOne)
// print(keyPathBuilder.testToOne.testEntityID)
XCTAssertAllEqual(
#keyPath(TestEntity1.testToOne.testEntityID),
(\TestEntity1.testToOne ~ \.testEntityID).description,
String(keyPath: \TestEntity1.testToOne ~ \.testEntityID)
// keyPathBuilder.testToOne.testEntityID.keyPathString
)
XCTAssertEqual(
XCTAssertAllEqual(
#keyPath(TestEntity1.testToOne.testToOne.testToManyUnordered),
(\TestEntity1.testToOne ~ \.testToOne ~ \.testToManyUnordered).description,
String(keyPath: \TestEntity1.testToOne ~ \.testToOne ~ \.testToManyUnordered)
)
XCTAssertEqual(
XCTAssertAllEqual(
#keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered),
(\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).description,
String(keyPath: \TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered)
@@ -84,17 +102,17 @@ final class WhereTests: XCTestCase {
}
do {
XCTAssertEqual(
XCTAssertAllEqual(
"master.pets",
(\Animal.master ~ \.pets).description,
String(keyPath: \Animal.master ~ \.pets)
)
XCTAssertEqual(
XCTAssertAllEqual(
"master.pets.species",
(\Animal.master ~ \.pets ~ \.species).description,
String(keyPath: \Animal.master ~ \.pets ~ \.species)
)
XCTAssertEqual(
XCTAssertAllEqual(
"master.pets.master",
(\Animal.master ~ \.pets ~ \.master).description,
String(keyPath: \Animal.master ~ \.pets ~ \.master)
@@ -105,12 +123,12 @@ final class WhereTests: XCTestCase {
do {
XCTAssertEqual(
XCTAssertAllEqual(
#keyPath(TestEntity1.testToOne.testToManyUnordered) + ".@count",
(\TestEntity1.testToOne ~ \.testToManyUnordered).count().description,
String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).count())
)
XCTAssertEqual(
XCTAssertAllEqual(
#keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered) + ".@count",
(\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).count().description,
String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).count())
@@ -118,7 +136,7 @@ final class WhereTests: XCTestCase {
}
do {
XCTAssertEqual(
XCTAssertAllEqual(
"master.pets.@count",
(\Animal.master ~ \.pets).count().description,
String(keyPath: (\Animal.master ~ \.pets).count())
@@ -129,12 +147,12 @@ final class WhereTests: XCTestCase {
do {
XCTAssertEqual(
XCTAssertAllEqual(
"ANY " + #keyPath(TestEntity1.testToOne.testToManyUnordered),
(\TestEntity1.testToOne ~ \.testToManyUnordered).any().description,
String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).any())
)
XCTAssertEqual(
XCTAssertAllEqual(
"ANY " + #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered),
(\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).any().description,
String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).any())
@@ -142,12 +160,12 @@ final class WhereTests: XCTestCase {
}
do {
XCTAssertEqual(
XCTAssertAllEqual(
"ANY master.pets",
(\Animal.master ~ \.pets).any().description,
String(keyPath: (\Animal.master ~ \.pets).any())
)
XCTAssertEqual(
XCTAssertAllEqual(
"ANY master.pets.species",
(\Animal.master ~ \.pets ~ \.species).any().description,
String(keyPath: (\Animal.master ~ \.pets ~ \.species).any())
@@ -158,12 +176,12 @@ final class WhereTests: XCTestCase {
do {
XCTAssertEqual(
XCTAssertAllEqual(
"ALL " + #keyPath(TestEntity1.testToOne.testToManyUnordered),
(\TestEntity1.testToOne ~ \.testToManyUnordered).all().description,
String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).all())
)
XCTAssertEqual(
XCTAssertAllEqual(
"ALL " + #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered),
(\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).all().description,
String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).all())
@@ -171,12 +189,12 @@ final class WhereTests: XCTestCase {
}
do {
XCTAssertEqual(
XCTAssertAllEqual(
"ALL master.pets",
(\Animal.master ~ \.pets).all().description,
String(keyPath: (\Animal.master ~ \.pets).all())
)
XCTAssertEqual(
XCTAssertAllEqual(
"ALL master.pets.species",
(\Animal.master ~ \.pets ~ \.species).all().description,
String(keyPath: (\Animal.master ~ \.pets ~ \.species).all())
@@ -187,12 +205,12 @@ final class WhereTests: XCTestCase {
do {
XCTAssertEqual(
XCTAssertAllEqual(
"NONE " + #keyPath(TestEntity1.testToOne.testToManyUnordered),
(\TestEntity1.testToOne ~ \.testToManyUnordered).none().description,
String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).none())
)
XCTAssertEqual(
XCTAssertAllEqual(
"NONE " + #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered),
(\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).none().description,
String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).none())
@@ -200,12 +218,12 @@ final class WhereTests: XCTestCase {
}
do {
XCTAssertEqual(
XCTAssertAllEqual(
"NONE master.pets",
(\Animal.master ~ \.pets).none().description,
String(keyPath: (\Animal.master ~ \.pets).none())
)
XCTAssertEqual(
XCTAssertAllEqual(
"NONE master.pets.species",
(\Animal.master ~ \.pets ~ \.species).none().description,
String(keyPath: (\Animal.master ~ \.pets ~ \.species).none())
@@ -224,15 +242,15 @@ final class WhereTests: XCTestCase {
let whereClause: Where<TestEntity1> = (\.testToOne ~ \.testString) == dummy
let predicate = NSPredicate(format: "\(#keyPath(TestEntity1.testToOne.testString)) == %@", dummy)
XCTAssertEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause: Where<Animal> = (\.master ~ \.name) == dummy
let predicate = NSPredicate(format: "master.name == %@", dummy)
XCTAssertEqual(whereClause, Where<Animal>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<Animal>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
do {
@@ -242,15 +260,15 @@ final class WhereTests: XCTestCase {
let whereClause: Where<TestEntity1> = (\.testToOne ~ \.testToOne ~ \.testString) == dummy
let predicate = NSPredicate(format: "\(#keyPath(TestEntity1.testToOne.testToOne.testString)) == %@", dummy)
XCTAssertEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause: Where<Animal> = (\.master ~ \.spouse ~ \.name) == dummy
let predicate = NSPredicate(format: "master.spouse.name == %@", dummy)
XCTAssertEqual(whereClause, Where<Animal>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<Animal>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
do {
@@ -260,15 +278,15 @@ final class WhereTests: XCTestCase {
let whereClause: Where<TestEntity1> = (\.testToOne ~ \.testToManyUnordered).count() == count
let predicate = NSPredicate(format: "\(#keyPath(TestEntity1.testToOne.testToManyUnordered)).@count == %d", count)
XCTAssertEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause: Where<Animal> = (\.master ~ \.pets).count() == count
let predicate = NSPredicate(format: "master.pets.@count == %d", count)
XCTAssertEqual(whereClause, Where<Animal>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<Animal>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
do {
@@ -278,15 +296,15 @@ final class WhereTests: XCTestCase {
let whereClause: Where<TestEntity1> = (\.testToOne ~ \.testToManyUnordered ~ \TestEntity1.testString).any() == dummy
let predicate = NSPredicate(format: "ANY \(#keyPath(TestEntity1.testToOne.testToManyUnordered)).\(#keyPath(TestEntity1.testString)) == %@", dummy)
XCTAssertEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause: Where<Animal> = (\.master ~ \.pets ~ \.species).any() == dummy
let predicate = NSPredicate(format: "ANY master.pets.species == %@", dummy)
XCTAssertEqual(whereClause, Where<Animal>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<Animal>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
do {
@@ -296,15 +314,15 @@ final class WhereTests: XCTestCase {
let whereClause: Where<TestEntity1> = (\.testToOne ~ \.testToManyUnordered ~ \TestEntity1.testString).all() == dummy
let predicate = NSPredicate(format: "ALL \(#keyPath(TestEntity1.testToOne.testToManyUnordered)).\(#keyPath(TestEntity1.testString)) == %@", dummy)
XCTAssertEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause: Where<Animal> = (\.master ~ \.pets ~ \.species).all() == dummy
let predicate = NSPredicate(format: "ALL master.pets.species == %@", dummy)
XCTAssertEqual(whereClause, Where<Animal>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<Animal>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
do {
@@ -314,15 +332,15 @@ final class WhereTests: XCTestCase {
let whereClause: Where<TestEntity1> = (\.testToOne ~ \.testToManyUnordered ~ \TestEntity1.testString).none() == dummy
let predicate = NSPredicate(format: "NONE \(#keyPath(TestEntity1.testToOne.testToManyUnordered)).\(#keyPath(TestEntity1.testString)) == %@", dummy)
XCTAssertEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<TestEntity1>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause: Where<Animal> = (\.master ~ \.pets ~ \.species).none() == dummy
let predicate = NSPredicate(format: "NONE master.pets.species == %@", dummy)
XCTAssertEqual(whereClause, Where<Animal>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<Animal>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
}
@@ -333,51 +351,51 @@ final class WhereTests: XCTestCase {
do {
let whereClause = Where<NSManagedObject>()
XCTAssertEqual(whereClause, Where<NSManagedObject>(true))
XCTAssertAllEqual(whereClause, Where<NSManagedObject>(true))
XCTAssertNotEqual(whereClause, Where<NSManagedObject>(false))
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
XCTAssertAllEqual(whereClause.predicate, NSPredicate(value: true))
}
do {
let whereClause = Where<NSManagedObject>(true)
XCTAssertEqual(whereClause, Where<NSManagedObject>())
XCTAssertAllEqual(whereClause, Where<NSManagedObject>())
XCTAssertNotEqual(whereClause, Where<NSManagedObject>(false))
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
XCTAssertAllEqual(whereClause.predicate, NSPredicate(value: true))
}
do {
let predicate = NSPredicate(format: "%K == %@", "key", "value")
let whereClause = Where<NSManagedObject>(predicate)
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where<NSManagedObject>("%K == %@", "key", "value")
let predicate = NSPredicate(format: "%K == %@", "key", "value")
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where<NSManagedObject>("%K == %@", argumentArray: ["key", "value"])
let predicate = NSPredicate(format: "%K == %@", "key", "value")
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where<NSManagedObject>("key", isEqualTo: "value")
let predicate = NSPredicate(format: "%K == %@", "key", "value")
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where<NSManagedObject>("key", isMemberOf: ["value1", "value2", "value3"])
let predicate = NSPredicate(format: "%K IN %@", "key", ["value1", "value2", "value3"])
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
XCTAssertAllEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertAllEqual(whereClause.predicate, predicate)
}
}
@@ -512,8 +530,8 @@ final class WhereTests: XCTestCase {
type: .not,
subpredicates: [whereClause1.predicate]
)
XCTAssertEqual(notWhere.predicate, notPredicate)
XCTAssertEqual(notWhere, !whereClause1)
XCTAssertAllEqual(notWhere.predicate, notPredicate)
XCTAssertAllEqual(notWhere, !whereClause1)
}
do {
@@ -528,8 +546,8 @@ final class WhereTests: XCTestCase {
whereClause3.predicate
]
)
XCTAssertEqual(andWhere.predicate, andPredicate)
XCTAssertEqual(andWhere, whereClause1 && whereClause2 && whereClause3)
XCTAssertAllEqual(andWhere.predicate, andPredicate)
XCTAssertAllEqual(andWhere, whereClause1 && whereClause2 && whereClause3)
}
do {
@@ -543,8 +561,8 @@ final class WhereTests: XCTestCase {
let unwrappedFinalSomeWhere = andWhere && someWhere!
XCTAssertEqual(andWhere.predicate, finalNoneWhere.predicate)
XCTAssertEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
XCTAssertAllEqual(andWhere.predicate, finalNoneWhere.predicate)
XCTAssertAllEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
}
do {
@@ -559,8 +577,8 @@ final class WhereTests: XCTestCase {
whereClause3.predicate
]
)
XCTAssertEqual(orWhere.predicate, orPredicate)
XCTAssertEqual(orWhere, whereClause1 || whereClause2 || whereClause3)
XCTAssertAllEqual(orWhere.predicate, orPredicate)
XCTAssertAllEqual(orWhere, whereClause1 || whereClause2 || whereClause3)
}
do {
@@ -573,8 +591,8 @@ final class WhereTests: XCTestCase {
let finalSomeWhere = orWhere &&? someWhere
let unwrappedFinalSomeWhere = orWhere && someWhere!
XCTAssertEqual(orWhere.predicate, finalNoneWhere.predicate)
XCTAssertEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
XCTAssertAllEqual(orWhere.predicate, finalNoneWhere.predicate)
XCTAssertAllEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
}
}
@@ -583,9 +601,9 @@ final class WhereTests: XCTestCase {
dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() {
let whereClause = Where<NSManagedObject>("key", isEqualTo: "value")
let request = CoreStoreFetchRequest<NSFetchRequestResult>()
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
whereClause.applyToFetchRequest(request)
XCTAssertNotNil(request.predicate)
XCTAssertEqual(request.predicate, whereClause.predicate)
XCTAssertAllEqual(request.predicate, whereClause.predicate)
}
}

View File

@@ -1,4 +1,4 @@
// swift-tools-version:4.2
// swift-tools-version:5.0
//
// Package.swift
// CoreStore
@@ -28,6 +28,9 @@ import PackageDescription
let package = Package(
name: "CoreStore",
platforms: [
.macOS(.v10_12), .iOS(.v10), .tvOS(.v10), .watchOS(.v3)
],
products: [
.library(name: "CoreStore", type: .static, targets: ["CoreStore"])
],
@@ -38,6 +41,13 @@ let package = Package(
dependencies: [],
path: "Sources",
exclude: ["CoreStoreBridge.h", "CoreStoreBridge.m"]
),
.testTarget(
name: "CoreStoreTests",
dependencies: ["CoreStore"],
path: "CoreStoreTests",
exclude: ["BridgingTests.h", "BridgingTests.m"]
)
]
],
swiftLanguageVersions: [.v5]
)

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

392
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ import CoreData
// MARK: - AsynchronousDataTransaction
/**
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:...)`.
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:...)`.
*/
public final class AsynchronousDataTransaction: BaseDataTransaction {
@@ -66,11 +66,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/
public override func create<D>(_ into: Into<D>) -> D {
public override func create<O>(_ into: Into<O>) -> O {
CoreStore.assert(
Internals.assert(
!self.isCommitted,
"Attempted to create an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
"Attempted to create an entity of type \(Internals.typeName(into.entityClass)) from an already committed \(Internals.typeName(self))."
)
return super.create(into)
@@ -82,11 +82,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be edited
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public override func edit<D: DynamicObject>(_ object: D?) -> D? {
public override func edit<O: DynamicObject>(_ object: O?) -> O? {
CoreStore.assert(
Internals.assert(
!self.isCommitted,
"Attempted to update an entity of type \(cs_typeName(object)) from an already committed \(cs_typeName(self))."
"Attempted to update an entity of type \(Internals.typeName(object)) from an already committed \(Internals.typeName(self))."
)
return super.edit(object)
@@ -99,60 +99,59 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public override func edit<D>(_ into: Into<D>, _ objectID: NSManagedObjectID) -> D? {
public override func edit<O>(_ into: Into<O>, _ objectID: NSManagedObjectID) -> O? {
CoreStore.assert(
Internals.assert(
!self.isCommitted,
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
"Attempted to update an entity of type \(Internals.typeName(into.entityClass)) from an already committed \(Internals.typeName(self))."
)
return super.edit(into, objectID)
}
/**
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
Deletes the objects with the specified `NSManagedObjectID`s.
- parameter objectIDs: the `NSManagedObjectID`s of the objects to delete
*/
public override func delete<D: DynamicObject>(_ object: D?) {
CoreStore.assert(
public override func delete<S: Sequence>(objectIDs: S) where S.Iterator.Element: NSManagedObjectID {
Internals.assert(
!self.isCommitted,
"Attempted to delete an entity of type \(cs_typeName(object)) from an already committed \(cs_typeName(self))."
"Attempted to delete an entities from an already committed \(Internals.typeName(self))."
)
super.delete(object)
super.delete(objectIDs: objectIDs)
}
/**
Deletes the specified `DynamicObject`s.
- parameter object1: the `DynamicObject` to be deleted
- parameter object2: another `DynamicObject` to be deleted
- parameter objects: other `DynamicObject`s to be deleted
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s represented by series of `ObjectRepresentation`s.
- parameter object: the `ObjectRepresentation` representing an `NSManagedObject` or `CoreStoreObject` to be deleted
- parameter objects: other `ObjectRepresentation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
*/
public override func delete<D: DynamicObject>(_ object1: D?, _ object2: D?, _ objects: D?...) {
CoreStore.assert(
public override func delete<O: ObjectRepresentation>(_ object: O?, _ objects: O?...) {
Internals.assert(
!self.isCommitted,
"Attempted to delete an entities from an already committed \(cs_typeName(self))."
"Attempted to delete an entities from an already committed \(Internals.typeName(self))."
)
super.delete(([object1, object2] + objects).compactMap { $0 })
super.delete(([object] + objects).compactMap { $0 })
}
/**
Deletes the specified `DynamicObject`s.
- parameter objects: the `DynamicObject`s to be deleted
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s represented by an `ObjectRepresenation`.
- parameter objects: the `ObjectRepresenation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
*/
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
CoreStore.assert(
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: ObjectRepresentation {
Internals.assert(
!self.isCommitted,
"Attempted to delete an entities from an already committed \(cs_typeName(self))."
"Attempted to delete an entities from an already committed \(Internals.typeName(self))."
)
super.delete(objects)
}

View File

@@ -29,11 +29,10 @@ import CoreData
// MARK: - AttributeProtocol
internal protocol AttributeProtocol: class {
internal protocol AttributeProtocol: PropertyProtocol {
static var attributeType: NSAttributeType { get }
var keyPath: KeyPathString { get }
var isOptional: Bool { get }
var isTransient: Bool { get }
var allowsExternalBinaryDataStorage: Bool { get }
@@ -44,4 +43,5 @@ internal protocol AttributeProtocol: class {
var rawObject: CoreStoreManagedObject? { get set }
var getter: CoreStoreManagedObject.CustomGetter? { get }
var setter: CoreStoreManagedObject.CustomSetter? { get }
var valueForSnapshot: Any? { get }
}

View File

@@ -39,13 +39,13 @@ extension BaseDataTransaction {
- throws: an `Error` thrown from any of the `ImportableObject` methods
- returns: the created `ImportableObject` instance, or `nil` if the import was ignored
*/
public func importObject<D: ImportableObject>(
_ into: Into<D>,
source: D.ImportSource) throws -> D? {
public func importObject<O: ImportableObject>(
_ into: Into<O>,
source: O.ImportSource) throws -> O? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
)
return try autoreleasepool {
@@ -65,22 +65,22 @@ extension BaseDataTransaction {
/**
Updates an existing `ImportableObject` by importing values from the specified import source.
- parameter object: the `NSManagedObject` to update
- parameter object: the `ImportableObject` to update
- parameter source: the object to import values from
- throws: an `Error` thrown from any of the `ImportableObject` methods
*/
public func importObject<D: ImportableObject>(
_ object: D,
source: D.ImportSource) throws {
public func importObject<O: ImportableObject>(
_ object: O,
source: O.ImportSource) throws {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(object)) outside the transaction's designated queue."
"Attempted to import an object of type \(Internals.typeName(object)) outside the transaction's designated queue."
)
try autoreleasepool {
let entityType = cs_dynamicType(of: object)
let entityType = object.runtimeType()
guard entityType.shouldInsert(from: source, in: self) else {
return
@@ -97,18 +97,18 @@ extension BaseDataTransaction {
- throws: an `Error` thrown from any of the `ImportableObject` methods
- returns: the array of created `ImportableObject` instances
*/
public func importObjects<D: ImportableObject, S: Sequence>(
_ into: Into<D>,
sourceArray: S) throws -> [D] where S.Iterator.Element == D.ImportSource {
public func importObjects<O: ImportableObject, S: Sequence>(
_ into: Into<O>,
sourceArray: S) throws -> [O] where S.Iterator.Element == O.ImportSource {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
)
return try autoreleasepool {
return try sourceArray.compactMap { (source) -> D? in
return try sourceArray.compactMap { (source) -> O? in
let entityType = into.entityClass
guard entityType.shouldInsert(from: source, in: self) else {
@@ -133,13 +133,13 @@ extension BaseDataTransaction {
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
- returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
*/
public func importUniqueObject<D: ImportableUniqueObject>(
_ into: Into<D>,
source: D.ImportSource) throws -> D? {
public func importUniqueObject<O: ImportableUniqueObject>(
_ into: Into<O>,
source: O.ImportSource) throws -> O? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
)
return try autoreleasepool {
@@ -151,7 +151,7 @@ extension BaseDataTransaction {
return nil
}
if let object = try self.fetchOne(From(entityType), Where<D>(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
if let object = try self.fetchOne(From(entityType), Where<O>(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
guard entityType.shouldUpdate(from: source, in: self) else {
@@ -185,23 +185,23 @@ extension BaseDataTransaction {
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
- returns: the array of created/updated `ImportableUniqueObject` instances
*/
public func importUniqueObjects<D: ImportableUniqueObject, S: Sequence>(
_ into: Into<D>,
public func importUniqueObjects<O: ImportableUniqueObject, S: Sequence>(
_ into: Into<O>,
sourceArray: S,
preProcess: @escaping (_ mapping: [D.UniqueIDType: D.ImportSource]) throws -> [D.UniqueIDType: D.ImportSource] = { $0 }) throws -> [D] where S.Iterator.Element == D.ImportSource {
preProcess: @escaping (_ mapping: [O.UniqueIDType: O.ImportSource]) throws -> [O.UniqueIDType: O.ImportSource] = { $0 }) throws -> [O] where S.Iterator.Element == O.ImportSource {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
"Attempted to import an object of type \(Internals.typeName(into.entityClass)) outside the transaction's designated queue."
)
return try autoreleasepool {
let entityType = into.entityClass
var importSourceByID = Dictionary<D.UniqueIDType, D.ImportSource>()
var importSourceByID = Dictionary<O.UniqueIDType, O.ImportSource>()
let sortedIDs = try autoreleasepool {
return try sourceArray.compactMap { (source) -> D.UniqueIDType? in
return try sourceArray.compactMap { (source) -> O.UniqueIDType? in
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
@@ -214,13 +214,13 @@ extension BaseDataTransaction {
importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
var existingObjectsByID = Dictionary<D.UniqueIDType, D>()
var existingObjectsByID = Dictionary<O.UniqueIDType, O>()
try self
.fetchAll(From(entityType), Where<D>(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))
.fetchAll(From(entityType), Where<O>(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
var processedObjectIDs = Set<D.UniqueIDType>()
var result = [D]()
var processedObjectIDs = Set<O.UniqueIDType>()
var result = [O]()
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {

View File

@@ -39,11 +39,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<D>(_ from: From<D>, _ deleteClauses: DeleteClause...) throws -> Int {
public func deleteAll<O>(_ from: From<O>, _ deleteClauses: DeleteClause...) throws -> Int {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
"Attempted to delete from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.deleteAll(from, deleteClauses)
}
@@ -56,11 +56,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<D>(_ from: From<D>, _ deleteClauses: [DeleteClause]) throws -> Int {
public func deleteAll<O>(_ from: From<O>, _ deleteClauses: [DeleteClause]) throws -> Int {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
"Attempted to delete from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.deleteAll(from, deleteClauses)
}
@@ -76,9 +76,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
@discardableResult
public func deleteAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
"Attempted to delete from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.deleteAll(clauseChain.from, clauseChain.fetchClauses)
@@ -93,7 +93,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter object: a reference to the object created/fetched outside the transaction
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
*/
public func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
public func fetchExisting<O: DynamicObject>(_ object: O) -> O? {
return self.context.fetchExisting(object)
}
@@ -104,7 +104,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
*/
public func fetchExisting<D: DynamicObject>(_ objectID: NSManagedObjectID) -> D? {
public func fetchExisting<O: DynamicObject>(_ objectID: NSManagedObjectID) -> O? {
return self.context.fetchExisting(objectID)
}
@@ -115,7 +115,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter objects: an array of `DynamicObject`s created/fetched outside the transaction
- returns: the `DynamicObject` array for objects that exists in the transaction
*/
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objects: S) -> [D] where S.Iterator.Element == D {
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objects: S) -> [O] where S.Iterator.Element == O {
return self.context.fetchExisting(objects)
}
@@ -126,7 +126,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `DynamicObject` array for objects that exists in the transaction
*/
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objectIDs: S) -> [D] where S.Iterator.Element == NSManagedObjectID {
public func fetchExisting<O: DynamicObject, S: Sequence>(_ objectIDs: S) -> [O] where S.Iterator.Element == NSManagedObjectID {
return self.context.fetchExisting(objectIDs)
}
@@ -139,11 +139,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchOne<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> D? {
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> O? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchOne(from, fetchClauses)
}
@@ -156,11 +156,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchOne<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> D? {
public func fetchOne<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> O? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchOne(from, fetchClauses)
}
@@ -180,9 +180,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> B.ObjectType? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchOne(clauseChain)
}
@@ -195,11 +195,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchAll<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> [D] {
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [O] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchAll(from, fetchClauses)
}
@@ -212,11 +212,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchAll<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> [D] {
public func fetchAll<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [O] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchAll(from, fetchClauses)
}
@@ -236,9 +236,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [B.ObjectType] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchAll(clauseChain)
}
@@ -251,11 +251,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchCount<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> Int {
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> Int {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchCount(from, fetchClauses)
}
@@ -268,11 +268,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the number of `DynamicObject`s that satisfy the specified `FetchClause`s
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchCount<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> Int {
public func fetchCount<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> Int {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchCount(from, fetchClauses)
}
@@ -292,9 +292,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchCount(clauseChain)
}
@@ -307,11 +307,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchObjectID(from, fetchClauses)
}
@@ -324,11 +324,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
public func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchObjectID(from, fetchClauses)
}
@@ -348,9 +348,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> NSManagedObjectID? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchObjectID(clauseChain)
}
@@ -363,11 +363,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchObjectIDs(from, fetchClauses)
}
@@ -380,11 +380,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
public func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchObjectIDs(from, fetchClauses)
}
@@ -404,9 +404,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [NSManagedObjectID] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.fetchObjectIDs(clauseChain)
}
@@ -425,11 +425,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) throws -> U? {
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: QueryClause...) throws -> U? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.queryValue(from, selectClause, queryClauses)
}
@@ -445,11 +445,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) throws -> U? {
public func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: [QueryClause]) throws -> U? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.queryValue(from, selectClause, queryClauses)
}
@@ -471,9 +471,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> B.ResultType? where B.ResultType: QueryableAttributeType {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
}
@@ -489,11 +489,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.queryAttributes(from, selectClause, queryClauses)
}
@@ -509,11 +509,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
public func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.queryAttributes(from, selectClause, queryClauses)
}
@@ -544,9 +544,9 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
*/
public func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> [[String: Any]] where B.ResultType == NSDictionary {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return try self.context.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
}

View File

@@ -50,17 +50,17 @@ public /*abstract*/ class BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/
public func create<D>(_ into: Into<D>) -> D {
public func create<O>(_ into: Into<O>) -> O {
let entityClass = into.entityClass
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
"Attempted to create an entity of type \(Internals.typeName(entityClass)) outside its designated queue."
)
let context = self.context
let dataStack = context.parentStack!
let entityIdentifier = EntityIdentifier(entityClass)
let entityIdentifier = Internals.EntityIdentifier(entityClass)
if into.inferStoreIfPossible {
switch dataStack.persistentStore(
@@ -77,10 +77,10 @@ public /*abstract*/ class BaseDataTransaction {
)
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.")
Internals.abort("Attempted to create an entity of type \(Internals.typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
default:
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)), but a destination persistent store containing the entity type could not be found.")
Internals.abort("Attempted to create an entity of type \(Internals.typeName(entityClass)), but a destination persistent store containing the entity type could not be found.")
}
}
else {
@@ -100,16 +100,16 @@ public /*abstract*/ class BaseDataTransaction {
)
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.")
Internals.abort("Attempted to create an entity of type \(Internals.typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
default:
if let configuration = into.configuration {
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) into the configuration \"\(configuration)\", which it doesn't belong to.")
Internals.abort("Attempted to create an entity of type \(Internals.typeName(entityClass)) into the configuration \"\(configuration)\", which it doesn't belong to.")
}
else {
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) into the default configuration, which it doesn't belong to.")
Internals.abort("Attempted to create an entity of type \(Internals.typeName(entityClass)) into the default configuration, which it doesn't belong to.")
}
}
}
@@ -121,11 +121,11 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` or `CoreStoreObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public func edit<D: DynamicObject>(_ object: D?) -> D? {
public func edit<O: DynamicObject>(_ object: O?) -> O? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to update an entity of type \(cs_typeName(object)) outside its designated queue."
"Attempted to update an entity of type \(Internals.typeName(object)) outside its designated queue."
)
guard let object = object else {
@@ -141,62 +141,69 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public func edit<D>(_ into: Into<D>, _ objectID: NSManagedObjectID) -> D? {
public func edit<O>(_ into: Into<O>, _ objectID: NSManagedObjectID) -> O? {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) outside its designated queue."
"Attempted to update an entity of type \(Internals.typeName(into.entityClass)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
into.inferStoreIfPossible
|| (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 \(Internals.typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
)
return self.fetchExisting(objectID)
}
/**
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
Deletes the objects with the specified `NSManagedObjectID`s.
- parameter objectIDs: the `NSManagedObjectID`s of the objects to delete
*/
public func delete<D: DynamicObject>(_ object: D?) {
CoreStore.assert(
public func delete<S: Sequence>(objectIDs: S) where S.Iterator.Element: NSManagedObjectID {
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete an entity outside its designated queue."
)
let context = self.context
object
.flatMap(context.fetchExisting)
.flatMap({ context.delete($0.cs_toRaw()) })
objectIDs.forEach {
context.fetchExisting($0).map(context.delete(_:))
}
}
/**
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s.
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s represented by series of `ObjectRepresentation`s.
- parameter object1: the `NSManagedObject` or `CoreStoreObject` to be deleted
- parameter object2: another `NSManagedObject` or `CoreStoreObject` to be deleted
- parameter objects: other `NSManagedObject`s or `CoreStoreObject`s to be deleted
- parameter object: the `ObjectRepresentation` representing an `NSManagedObject` or `CoreStoreObject` to be deleted
- parameter objects: other `ObjectRepresentation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
*/
public func delete<D: DynamicObject>(_ object1: D?, _ object2: D?, _ objects: D?...) {
public func delete<O: ObjectRepresentation>(_ object: O?, _ objects: O?...) {
self.delete(([object1, object2] + objects).compactMap { $0 })
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete an entity outside its designated queue."
)
self.delete(([object] + objects).compactMap { $0 })
}
/**
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s.
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s represented by an `ObjectRepresenation`.
- parameter objects: the `NSManagedObject`s or `CoreStoreObject`s to be deleted
- parameter objects: the `ObjectRepresenation`s representing `NSManagedObject`s or `CoreStoreObject`s to be deleted
*/
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: ObjectRepresentation {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete entities outside their designated queue."
)
let context = self.context
objects.forEach { context.fetchExisting($0).flatMap({ context.delete($0.cs_toRaw()) }) }
objects.forEach {
$0.asEditable(in: self).map({ context.delete($0.cs_toRaw()) })
}
}
/**
@@ -204,7 +211,7 @@ public /*abstract*/ class BaseDataTransaction {
*/
public func refreshAndMergeAllObjects() {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to refresh entities outside their designated queue."
)
@@ -213,6 +220,25 @@ public /*abstract*/ class BaseDataTransaction {
// MARK: Inspecting Pending Objects
/**
Returns `true` if the object has any property values changed. This method should not be called after the `commit()` method was called.
- parameter object: the `DynamicObject` instance
- returns: `true` if the object has any property values changed.
*/
public func objectHasPersistentChangedValues<O: DynamicObject>(_ object: O) -> Bool {
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access inserted objects from a \(Internals.typeName(self)) outside its designated queue."
)
Internals.assert(
!self.isCommitted,
"Attempted to access inserted objects from an already committed \(Internals.typeName(self))."
)
return object.cs_toRaw().hasPersistentChangedValues
}
/**
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.
@@ -220,15 +246,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were inserted to the transaction.
*/
public func insertedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
public func insertedObjects<O: DynamicObject>(_ entity: O.Type) -> Set<O> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access inserted objects from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!self.isCommitted,
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
"Attempted to access inserted objects from an already committed \(Internals.typeName(self))."
)
return Set(self.context.insertedObjects.compactMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
@@ -240,13 +266,13 @@ public /*abstract*/ class BaseDataTransaction {
*/
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access inserted object IDs from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!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 \(Internals.typeName(self))."
)
return Set(self.context.insertedObjects.map { $0.objectID })
}
@@ -257,15 +283,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/
public func insertedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
public func insertedObjectIDs<O: DynamicObject>(_ entity: O.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access inserted object IDs from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!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 \(Internals.typeName(self))."
)
return Set(self.context.insertedObjects.compactMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}
@@ -276,15 +302,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were updated in the transaction.
*/
public func updatedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
public func updatedObjects<O: DynamicObject>(_ entity: O.Type) -> Set<O> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access updated objects from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!self.isCommitted,
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
"Attempted to access updated objects from an already committed \(Internals.typeName(self))."
)
return Set(self.context.updatedObjects.compactMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
@@ -296,13 +322,13 @@ public /*abstract*/ class BaseDataTransaction {
*/
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access updated object IDs from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!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 \(Internals.typeName(self))."
)
return Set(self.context.updatedObjects.map { $0.objectID })
}
@@ -313,15 +339,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/
public func updatedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
public func updatedObjectIDs<O: DynamicObject>(_ entity: O.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access updated object IDs from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!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 \(Internals.typeName(self))."
)
return Set(self.context.updatedObjects.compactMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}
@@ -332,15 +358,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were deleted from the transaction.
*/
public func deletedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
public func deletedObjects<O: DynamicObject>(_ entity: O.Type) -> Set<O> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access deleted objects from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!self.isCommitted,
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
"Attempted to access deleted objects from an already committed \(Internals.typeName(self))."
)
return Set(self.context.deletedObjects.compactMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
@@ -353,13 +379,13 @@ public /*abstract*/ class BaseDataTransaction {
*/
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access deleted object IDs from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!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 \(Internals.typeName(self))."
)
return Set(self.context.deletedObjects.map { $0.objectID })
}
@@ -370,15 +396,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
public func deletedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
public func deletedObjectIDs<O: DynamicObject>(_ entity: O.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
Internals.assert(
self.isRunningInAllowedQueue(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
"Attempted to access deleted object IDs from a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!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 \(Internals.typeName(self))."
)
return Set(self.context.deletedObjects.compactMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `AsynchronousDataTransaction`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
@@ -46,13 +47,13 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreSto
@objc
public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
CoreStore.assert(
Internals.assert(
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
"Attempted to commit a \(Internals.typeName(self)) outside its designated queue."
)
CoreStore.assert(
Internals.assert(
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
"Attempted to commit a \(Internals.typeName(self)) more than once."
)
self.bridgeToSwift.autoCommit { (_, error) in
@@ -72,7 +73,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreSto
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -161,6 +162,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreSto
// MARK: - AsynchronousDataTransaction
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension AsynchronousDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -89,9 +89,9 @@ extension CSBaseDataTransaction {
@objc
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
CoreStore.assert(
Internals.assert(
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchOne(from, fetchClauses))?
.flatMap({ $0 })
@@ -107,9 +107,9 @@ extension CSBaseDataTransaction {
@objc
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
CoreStore.assert(
Internals.assert(
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchAll(from, fetchClauses))
.flatMap({ $0 })
@@ -125,9 +125,9 @@ extension CSBaseDataTransaction {
@objc
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
CoreStore.assert(
Internals.assert(
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchCount(from, fetchClauses))
.flatMap({ NSNumber(value: $0) })
@@ -143,9 +143,9 @@ extension CSBaseDataTransaction {
@objc
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
Internals.assert(
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.fetchObjectID(from, fetchClauses))
.flatMap({ $0 })
@@ -164,9 +164,9 @@ extension CSBaseDataTransaction {
@objc
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
CoreStore.assert(
Internals.assert(
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.queryValue(from, selectClause, queryClauses))
.flatMap({ $0 })
@@ -185,9 +185,9 @@ extension CSBaseDataTransaction {
@objc
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
CoreStore.assert(
Internals.assert(
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
"Attempted to query from a \(Internals.typeName(self)) outside its designated queue."
)
return (try? self.swiftTransaction.context.queryAttributes(from, selectClause, queryClauses))
.flatMap({ $0 })

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSCoreStore
@available(*, deprecated, message: "Call methods directly from the CSDataStack instead")
extension CSCoreStore {
/**

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSCoreStore
@available(*, deprecated, message: "Call methods directly from the CSDataStack instead")
@available(macOS 10.12, *)
extension CSCoreStore {

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSCoreStore
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
extension CSCoreStore {
/**

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSCoreStore
@available(*, deprecated, message: "Call methods directly from the CSDataStack instead")
extension CSCoreStore {
/**
@@ -37,7 +38,7 @@ extension CSCoreStore {
@objc
public static var modelVersion: String {
return CoreStore.modelVersion
return self.defaultStack.modelVersion
}
/**
@@ -46,7 +47,7 @@ extension CSCoreStore {
@objc
public static func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return CoreStore.entityTypesByName(for: type)
return self.defaultStack.bridgeToSwift.entityTypesByName(for: type)
}
/**
@@ -55,7 +56,7 @@ extension CSCoreStore {
@objc
public static func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? {
return CoreStore.entityDescription(for: type)
return self.defaultStack.bridgeToSwift.entityDescription(for: type)
}
/**

View File

@@ -28,6 +28,7 @@ import Foundation
// MARK: - CSCoreStore
@available(*, deprecated, message: "Call methods directly from the CSDataStack instead")
extension CSCoreStore {
/**
@@ -64,7 +65,7 @@ extension CSCoreStore {
return bridge {
CoreStore.beginUnsafe()
self.defaultStack.bridgeToSwift.beginUnsafe()
}
}
@@ -79,7 +80,7 @@ extension CSCoreStore {
return bridge {
CoreStore.beginUnsafe(supportsUndo: supportsUndo)
self.defaultStack.bridgeToSwift.beginUnsafe(supportsUndo: supportsUndo)
}
}
@@ -89,6 +90,6 @@ extension CSCoreStore {
@objc
public static func refreshAndMergeAllObjects() {
CoreStore.refreshAndMergeAllObjects()
self.defaultStack.refreshAndMergeAllObjects()
}
}

View File

@@ -33,6 +33,7 @@ import Foundation
- SeeAlso: `CoreStore`
*/
@available(*, deprecated, message: "Call methods directly from the CSDataStack instead")
@objc
public final class CSCoreStore: NSObject {
@@ -45,14 +46,8 @@ public final class CSCoreStore: NSObject {
@objc
public static var defaultStack: CSDataStack {
get {
return CoreStore.defaultStack.bridgeToObjectiveC
}
set {
CoreStore.defaultStack = newValue.bridgeToSwift
}
get { return CoreStoreDefaults.dataStack.bridgeToObjectiveC }
set { CoreStoreDefaults.dataStack = newValue.bridgeToSwift }
}

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CSDataStack {
/**

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@available(macOS 10.12, *)
extension CSDataStack {
@@ -36,7 +37,7 @@ extension CSDataStack {
Creates a `CSObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`.
- parameter object: the `NSManagedObject` to observe changes from
- returns: a `ObjectMonitor` that monitors changes to `object`
- returns: an `ObjectMonitor` that monitors changes to `object`
*/
@objc
public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
@@ -54,11 +55,11 @@ extension CSDataStack {
@objc
public func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
CoreStore.assert(
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires a CSOrderBy clause."
)
@@ -83,11 +84,11 @@ extension CSDataStack {
@objc
public func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
CoreStore.assert(
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)
@@ -117,11 +118,11 @@ extension CSDataStack {
@objc
public func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
CoreStore.assert(
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)
@@ -146,11 +147,11 @@ extension CSDataStack {
*/
public func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
"Attempted to observe objects from \(Internals.typeName(self)) outside the main thread."
)
CoreStore.assert(
Internals.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CSDataStack {
/**
@@ -89,9 +90,9 @@ extension CSDataStack {
@objc
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchOne(from, fetchClauses))?
.flatMap({ $0 })
@@ -107,9 +108,9 @@ extension CSDataStack {
@objc
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchAll(from, fetchClauses))
.flatMap({ $0 })
@@ -125,9 +126,9 @@ extension CSDataStack {
@objc
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchCount(from, fetchClauses))
.flatMap({ NSNumber(value: $0) })
@@ -143,9 +144,9 @@ extension CSDataStack {
@objc
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchObjectID(from, fetchClauses))?
.flatMap({ $0 })
@@ -161,9 +162,9 @@ extension CSDataStack {
@objc
public func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
"Attempted to fetch from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.fetchObjectIDs(from, fetchClauses))
.flatMap({ $0 })
@@ -182,9 +183,9 @@ extension CSDataStack {
@objc
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread."
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.queryValue(from, selectClause, queryClauses))
.flatMap({ $0 })
@@ -203,9 +204,9 @@ extension CSDataStack {
@objc
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
CoreStore.assert(
Internals.assert(
Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread."
"Attempted to query from a \(Internals.typeName(self)) outside the main thread."
)
return (try? self.bridgeToSwift.mainContext.queryAttributes(from, selectClause, queryClauses))
.flatMap({ $0 })

View File

@@ -28,6 +28,7 @@ import Foundation
// MARK: - CSDataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CSDataStack {
/**
@@ -45,9 +46,9 @@ extension CSDataStack {
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
CoreStore.log(
Internals.log(
.warning,
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
message: "The closure for the \(Internals.typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
try transaction.cancel()
@@ -77,9 +78,9 @@ extension CSDataStack {
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
CoreStore.log(
Internals.log(
.warning,
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
message: "The closure for the \(Internals.typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
try transaction.cancel()

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `DataStack`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
@@ -191,7 +192,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -209,6 +210,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
// MARK: - DataStack
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension DataStack: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `CoreStoreError`
*/
@objc
public final class CSError: NSError, CoreStoreObjectiveCType {
public final class CSError: NSError {
/**
The `NSError` error domain for `CSError`.
@@ -64,21 +64,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CoreStoreObjectiveCType
public var bridgeToSwift: CoreStoreError {
if let swift = self.swiftError {
return swift
}
let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
self.swiftError = swift
return swift
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
/**
@@ -101,6 +87,23 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
private var swiftError: CoreStoreError?
}
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CSError: CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType
public var bridgeToSwift: CoreStoreError {
if let swift = self.swiftError {
return swift
}
let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
self.swiftError = swift
return swift
}
}
// MARK: - CSErrorCode
@@ -110,6 +113,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
- SeeAlso: `CSError`
- SeeAlso: `CoreStoreError`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public enum CSErrorCode: Int {
@@ -152,6 +156,7 @@ public enum CSErrorCode: Int {
// MARK: - CoreStoreError
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
// MARK: CoreStoreSwiftType
@@ -274,14 +279,15 @@ extension Error {
case let error as CSError:
return error.bridgeToSwift
case let error as NSError where type(of: self) is NSError.Type:
case let error as NSError where Self.self is NSError.Type:
return .internalError(NSError: error)
default:
return .unknown
}
}
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
internal var bridgeToObjectiveC: NSError {
switch self {

View File

@@ -97,7 +97,7 @@ public final class CSFrom: NSObject {
self.init(From(entityClass, nil))
default:
CoreStore.abort("The configuration argument only accepts NSString and NSNull values")
Internals.abort("The configuration argument only accepts NSString and NSNull values")
}
}
@@ -126,7 +126,7 @@ public final class CSFrom: NSObject {
arguments.append(nil)
default:
CoreStore.abort("The configurations argument only accepts NSString and NSNull values")
Internals.abort("The configurations argument only accepts NSString and NSNull values")
}
}
self.init(From(entityClass, arguments))
@@ -137,7 +137,7 @@ public final class CSFrom: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -145,7 +145,7 @@ public final class CSFrom: NSObject {
public let bridgeToSwift: From<NSManagedObject>
public init<D: NSManagedObject>(_ swiftValue: From<D>) {
public init<O: NSManagedObject>(_ swiftValue: From<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -155,7 +155,7 @@ public final class CSFrom: NSObject {
// MARK: - From
extension From where D: NSManagedObject {
extension From where O: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -87,7 +87,7 @@ public final class CSGroupBy: NSObject, CSQueryClause {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -104,7 +104,7 @@ public final class CSGroupBy: NSObject, CSQueryClause {
public let bridgeToSwift: GroupBy<NSManagedObject>
public init<D: NSManagedObject>(_ swiftValue: GroupBy<D>) {
public init<O: NSManagedObject>(_ swiftValue: GroupBy<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -114,7 +114,7 @@ public final class CSGroupBy: NSObject, CSQueryClause {
// MARK: - GroupBy
extension GroupBy where D: NSManagedObject {
extension GroupBy where O: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `InMemoryStore`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjectiveCType {
@@ -103,7 +104,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -121,6 +122,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
// MARK: - InMemoryStore
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension InMemoryStore: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -104,7 +104,7 @@ public final class CSInto: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -112,7 +112,7 @@ public final class CSInto: NSObject {
public let bridgeToSwift: Into<NSManagedObject>
public required init<D: NSManagedObject>(_ swiftValue: Into<D>) {
public required init<O: NSManagedObject>(_ swiftValue: Into<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -122,7 +122,7 @@ public final class CSInto: NSObject {
// MARK: - Into
extension Into where D: NSManagedObject {
extension Into where O: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -526,7 +526,7 @@ public final class CSListMonitor: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}

View File

@@ -42,7 +42,7 @@ import CoreData
*/
@available(macOS 10.12, *)
@objc
public protocol CSListObserver: class {
public protocol CSListObserver: AnyObject {
/**
Handles processing just before a change to the observed list occurs

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `MigrationResult`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@@ -155,7 +156,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -173,6 +174,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
// MARK: - MigrationResult
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension MigrationResult {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `MigrationType`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
@@ -101,7 +102,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -119,6 +120,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
// MARK: - MigrationType
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension MigrationType: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -119,7 +119,7 @@ public final class CSObjectMonitor: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}

View File

@@ -40,7 +40,7 @@ import CoreData
*/
@available(macOS 10.12, *)
@objc
public protocol CSObjectObserver: class {
public protocol CSObjectObserver: AnyObject {
/**
Handles processing just before a change to the observed `object` occurs

View File

@@ -95,7 +95,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -112,7 +112,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
public let bridgeToSwift: OrderBy<NSManagedObject>
public init<D: NSManagedObject>(_ swiftValue: OrderBy<D>) {
public init<O: NSManagedObject>(_ swiftValue: OrderBy<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -122,7 +122,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
// MARK: - OrderBy
extension OrderBy where D: NSManagedObject {
extension OrderBy where O: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `SQLiteStore`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCType {
@@ -178,7 +179,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -196,6 +197,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
// MARK: - SQLiteStore
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension SQLiteStore: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -68,7 +68,7 @@ public final class CSSectionBy: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -76,7 +76,7 @@ public final class CSSectionBy: NSObject {
public let bridgeToSwift: SectionBy<NSManagedObject>
public init<D>(_ swiftValue: SectionBy<D>) {
public init<O>(_ swiftValue: SectionBy<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()

View File

@@ -177,7 +177,7 @@ public final class CSSelectTerm: NSObject {
public let bridgeToSwift: SelectTerm<NSManagedObject>
public init<D: NSManagedObject>(_ swiftValue: SelectTerm<D>) {
public init<O: NSManagedObject>(_ swiftValue: SelectTerm<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -187,7 +187,7 @@ public final class CSSelectTerm: NSObject {
// MARK: - SelectTerm
extension SelectTerm where D: NSManagedObject {
extension SelectTerm where O: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -377,13 +377,13 @@ public final class CSSelect: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CoreStoreObjectiveCType
public init<D: NSManagedObject, T: QueryableAttributeType>(_ swiftValue: Select<D, T>) {
public init<O: NSManagedObject, T: QueryableAttributeType>(_ swiftValue: Select<O, T>) {
self.attributeType = T.cs_rawAttributeType
self.selectTerms = swiftValue.selectTerms.map({ $0.downcast() })
@@ -391,7 +391,7 @@ public final class CSSelect: NSObject {
super.init()
}
public init<D: NSManagedObject, T>(_ swiftValue: Select<D, T>) {
public init<O: NSManagedObject, T>(_ swiftValue: Select<O, T>) {
self.attributeType = .undefinedAttributeType
self.selectTerms = swiftValue.selectTerms.map({ $0.downcast() })
@@ -467,9 +467,9 @@ public final class CSSelect: NSObject {
}
else {
CoreStore.log(
Internals.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."
message: "The key path \"\(keyPath)\" could not be resolved in entity \(Internals.typeName(entityDescription.managedObjectClassName)) as an attribute and will be ignored by \(Internals.typeName(self)) query clause."
)
}
@@ -502,7 +502,7 @@ public final class CSSelect: NSObject {
// MARK: - Select
extension Select where D: NSManagedObject {
extension Select where O: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `SetupResult`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSSetupResult: NSObject {
@@ -146,7 +147,7 @@ public final class CSSetupResult: NSObject {
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -177,6 +178,7 @@ public final class CSSetupResult: NSObject {
// MARK: - SetupResult
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension SetupResult where Success: StorageInterface, Success: CoreStoreSwiftType, Success.ObjectiveCType: CSStorageInterface, Failure == CoreStoreError {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `SynchronousDataTransaction`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSSynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
@@ -60,7 +61,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction, CoreStor
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -148,6 +149,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction, CoreStor
// MARK: - SynchronousDataTransaction
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension SynchronousDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `Tweak`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSTweak: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause, CoreStoreObjectiveCType {
@@ -63,7 +64,7 @@ public final class CSTweak: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -90,6 +91,7 @@ public final class CSTweak: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
// MARK: - Tweak
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension Tweak: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import Foundation
- SeeAlso: `UnsafeDataModelSchema`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSUnsafeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
@@ -71,7 +72,7 @@ public final class CSUnsafeDataModelSchema: NSObject, CSDynamicSchema, CoreStore
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -104,6 +105,7 @@ public final class CSUnsafeDataModelSchema: NSObject, CSDynamicSchema, CoreStore
// MARK: - UnsafeDataModelSchema
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension UnsafeDataModelSchema: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -34,6 +34,7 @@ import CoreData
- SeeAlso: `UnsafeDataTransaction`
*/
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
@objc
public final class CSUnsafeDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
/**
@@ -181,7 +182,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction, CoreStoreObje
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -208,6 +209,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction, CoreStoreObje
// MARK: - UnsafeDataTransaction
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension UnsafeDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -134,7 +134,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -151,7 +151,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
public let bridgeToSwift: Where<NSManagedObject>
public init<D: NSManagedObject>(_ swiftValue: Where<D>) {
public init<O: NSManagedObject>(_ swiftValue: Where<O>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -161,7 +161,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
// MARK: - Where
extension Where where D: NSManagedObject {
extension Where where O: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -35,6 +35,7 @@ import Foundation
- SeeAlso: `XcodeDataModelSchema`
*/
@objc
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
/**
@@ -71,7 +72,7 @@ public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreO
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: Self.self))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -104,6 +105,7 @@ public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreO
// MARK: - XcodeDataModelSchema
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
extension XcodeDataModelSchema: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType

View File

@@ -33,7 +33,7 @@ import CoreData
Objective-C Foundation types that are natively supported by Core Data managed attributes all conform to `CoreDataNativeType`.
*/
@objc
public protocol CoreDataNativeType: class, NSObjectProtocol {}
public protocol CoreDataNativeType: AnyObject, NSObjectProtocol {}
// MARK: - NSNumber

View File

@@ -54,50 +54,6 @@ extension AsynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDe
}
// MARK: - CloudStorageOptions
extension CloudStorageOptions: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
var flags = [String]()
if self.contains(.recreateLocalStoreOnModelMismatch) {
flags.append(".recreateLocalStoreOnModelMismatch")
}
if self.contains(.allowSynchronousLightweightMigration) {
flags.append(".allowSynchronousLightweightMigration")
}
switch flags.count {
case 0:
return "[.none]"
case 1:
return "[.\(flags[0])]"
default:
var string = "[\n"
string.append(flags.joined(separator: ",\n"))
string.indent(1)
string.append("\n]")
return string
}
}
}
// MARK: - CoreStoreError
extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -116,7 +72,7 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
let firstLine: String
var info: DumpInfo = [
("errorDomain", type(of: self).errorDomain),
("errorDomain", Self.errorDomain),
("errorCode", self.errorCode),
]
switch self {
@@ -417,15 +373,34 @@ fileprivate struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConve
var coreStoreDumpString: String {
return createFormattedString(
"\"\(self.sectionInfo.name)\" (", ")",
("numberOfObjects", self.sectionInfo.numberOfObjects),
("indexTitle", self.sectionInfo.indexTitle as Any)
"\"\(self.sectionName)\" (", ")",
("numberOfObjects", self.numberOfObjects),
("indexTitle", self.sectionIndexTitle as Any)
)
}
// MARK: FilePrivate
let sectionInfo: NSFetchedResultsSectionInfo
fileprivate init(_ sectionInfo: NSFetchedResultsSectionInfo) {
self.sectionName = sectionInfo.name
self.numberOfObjects = sectionInfo.numberOfObjects
self.sectionIndexTitle = sectionInfo.indexTitle
}
fileprivate init(_ section: Internals.DiffableDataSourceSnapshot.Section) {
self.sectionName = section.differenceIdentifier
self.numberOfObjects = section.elements.count
self.sectionIndexTitle = nil
}
// MARK: Private
private let sectionName: String
private let sectionIndexTitle: String?
private let numberOfObjects: Int
}
@available(macOS 10.12, *)
@@ -453,6 +428,56 @@ extension ListMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvert
}
// MARK: - ListPublisher
@available(macOS 10.12, *)
extension ListPublisher: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("snapshot", self.snapshot)
)
}
}
// MARK: - ListSnapshot
extension ListSnapshot: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("numberOfObjects", self.numberOfItems),
("sections", self.diffableSnapshot.sections.map(CoreStoreFetchedSectionInfoWrapper.init))
)
}
}
// MARK: - LocalStorageOptions
extension LocalStorageOptions: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -612,6 +637,56 @@ extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConve
}
// MARK: - ObjectPublisher
extension ObjectPublisher: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("objectID", self.objectID()),
("object", self.object as Any)
)
}
}
// MARK: - ObjectSnapshot
extension ObjectSnapshot: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
return createFormattedString(
"(", ")",
("objectID", self.objectID()),
("dictionaryForValues", self.dictionaryForValues())
)
}
}
// MARK: - OrderBy
extension OrderBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -1204,7 +1279,7 @@ extension NSEntityDescription: CoreStoreDebugStringConvertible {
info.append(("compoundIndexes", self.compoundIndexes))
}
if #available(macOS 10.11, *) {
if #available(macOS 10.11, iOS 9.0, *) {
info.append(("uniquenessConstraints", self.uniquenessConstraints))
}

View File

@@ -26,22 +26,16 @@
import Foundation
// MARK: - CoreStore
// MARK: - Internal
extension Internals {
extension CoreStore {
/**
The `CoreStoreLogger` instance to be used. The default logger is an instance of a `DefaultLogger`.
*/
public static var logger: CoreStoreLogger = DefaultLogger()
// MARK: Internal
@inline(__always)
internal static func log(_ level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
self.logger.log(
CoreStoreDefaults.logger.log(
level: level,
message: message,
fileName: fileName,
@@ -49,11 +43,11 @@ extension CoreStore {
functionName: functionName
)
}
@inline(__always)
internal static func log(_ error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
self.logger.log(
CoreStoreDefaults.logger.log(
error: error,
message: message,
fileName: fileName,
@@ -61,11 +55,11 @@ extension CoreStore {
functionName: functionName
)
}
@inline(__always)
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
self.logger.assert(
CoreStoreDefaults.logger.assert(
condition(),
message: message(),
fileName: fileName,
@@ -73,11 +67,11 @@ extension CoreStore {
functionName: functionName
)
}
@inline(__always)
internal static func abort(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) -> Never {
self.logger.abort(
CoreStoreDefaults.logger.abort(
message,
fileName: fileName,
lineNumber: lineNumber,

View File

@@ -29,12 +29,13 @@ import CoreData
// MARK: - CoreStore
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
extension CoreStore {
/**
Asynchronously adds a `StorageInterface` to the `defaultStack`. Migrations are also initiated by default.
Asynchronously adds a `StorageInterface` to the `CoreStoreDefaults.dataStack`. Migrations are also initiated by default.
```
CoreStore.addStorage(
dataStack.addStorage(
InMemoryStore(configuration: "Config1"),
completion: { result in
switch result {
@@ -49,13 +50,13 @@ extension CoreStore {
*/
public static func addStorage<T>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
self.defaultStack.addStorage(storage, completion: completion)
CoreStoreDefaults.dataStack.addStorage(storage, completion: completion)
}
/**
Asynchronously adds a `LocalStorage` to the `defaultStack`. Migrations are also initiated by default.
Asynchronously adds a `LocalStorage` to the `CoreStoreDefaults.dataStack`. Migrations are also initiated by default.
```
let migrationProgress = CoreStore.addStorage(
let migrationProgress = dataStack.addStorage(
SQLiteStore(fileName: "core_data.sqlite", configuration: "Config1"),
completion: { result in
switch result {
@@ -71,43 +72,11 @@ extension CoreStore {
*/
public static func addStorage<T: LocalStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) -> Progress? {
return self.defaultStack.addStorage(storage, completion: completion)
}
/**
Asynchronously adds a `CloudStorage` to the `defaultStack`. Migrations are also initiated by default.
```
guard let storage = ICloudStore(
ubiquitousContentName: "MyAppCloudData",
ubiquitousContentTransactionLogsSubdirectory: "logs/config1",
ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
configuration: "Config1",
cloudStorageOptions: .recreateLocalStoreOnModelMismatch
) else {
// iCloud is not available on the device
return
}
let migrationProgress = dataStack.addStorage(
storage,
completion: { result in
switch result {
case .success(let storage): // ...
case .failure(let error): // ...
}
}
)
```
- parameter storage: the cloud 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 `CloudStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
*/
public static func addStorage<T: CloudStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
self.defaultStack.addStorage(storage, completion: completion)
return CoreStoreDefaults.dataStack.addStorage(storage, completion: completion)
}
/**
Migrates a local storage to match the `defaultStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
Migrates a local storage to match the `CoreStoreDefaults.dataStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
- parameter storage: the local storage
- parameter completion: the closure to be executed on the main queue when the migration completes, either due to success or failure. The closure's `MigrationResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.failure` result if an error occurs asynchronously.
@@ -116,11 +85,11 @@ extension CoreStore {
*/
public static func upgradeStorageIfNeeded<T: LocalStorage>(_ storage: T, completion: @escaping (MigrationResult) -> Void) throws -> Progress? {
return try self.defaultStack.upgradeStorageIfNeeded(storage, completion: completion)
return try CoreStoreDefaults.dataStack.upgradeStorageIfNeeded(storage, completion: completion)
}
/**
Checks the migration steps required for the storage to match the `defaultStack`'s managed object model version.
Checks the migration steps required for the storage to match the `CoreStoreDefaults.dataStack`'s managed object model version.
- parameter storage: the local storage
- throws: a `CoreStoreError` value indicating the failure
@@ -128,6 +97,6 @@ extension CoreStore {
*/
public static func requiredMigrationsForStorage<T: LocalStorage>(_ storage: T) throws -> [MigrationType] {
return try self.defaultStack.requiredMigrationsForStorage(storage)
return try CoreStoreDefaults.dataStack.requiredMigrationsForStorage(storage)
}
}

View File

@@ -29,48 +29,49 @@ import CoreData
// MARK: - CoreStore
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
@available(macOS 10.12, *)
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`.
Using the `CoreStoreDefaults.dataStack`, 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`
- returns: an `ObjectMonitor` that monitors changes to `object`
*/
public static func monitorObject<D>(_ object: D) -> ObjectMonitor<D> {
public static func monitorObject<O: DynamicObject>(_ object: O) -> ObjectMonitor<O> {
return self.defaultStack.monitorObject(object)
return CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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> {
public static func monitorList<O>(_ from: From<O>, _ fetchClauses: FetchClause...) -> ListMonitor<O> {
return self.defaultStack.monitorList(from, fetchClauses)
return CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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> {
public static func monitorList<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) -> ListMonitor<O> {
return self.defaultStack.monitorList(from, fetchClauses)
return CoreStoreDefaults.dataStack.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(
let monitor = dataStack.monitorList(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
@@ -81,38 +82,38 @@ extension CoreStore {
*/
public static func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
return self.defaultStack.monitorList(clauseChain.from, clauseChain.fetchClauses)
return CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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...) {
public static func monitorList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ fetchClauses: FetchClause...) {
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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]) {
public static func monitorList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ fetchClauses: [FetchClause]) {
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
CoreStoreDefaults.dataStack.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(
dataStack.monitorList(
createAsynchronously: { (monitor) in
self.monitor = monitor
},
@@ -126,7 +127,7 @@ extension CoreStore {
*/
public static func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
self.defaultStack.monitorList(
CoreStoreDefaults.dataStack.monitorList(
createAsynchronously: createAsynchronously,
clauseChain.from,
clauseChain.fetchClauses
@@ -134,35 +135,35 @@ extension CoreStore {
}
/**
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.
Using the `CoreStoreDefaults.dataStack`, 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> {
public static func monitorSectionedList<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) -> ListMonitor<O> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
return CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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> {
public static func monitorSectionedList<O>(_ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) -> ListMonitor<O> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
return CoreStoreDefaults.dataStack.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(
let monitor = dataStack.monitorSectionedList(
From<MyPersonEntity>()
.sectionBy(\.age, { "\($0!) years old" })
.where(\.age > 18)
@@ -174,7 +175,7 @@ extension CoreStore {
*/
public static func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
return self.defaultStack.monitorSectionedList(
return CoreStoreDefaults.dataStack.monitorSectionedList(
clauseChain.from,
clauseChain.sectionBy,
clauseChain.fetchClauses
@@ -182,35 +183,35 @@ extension CoreStore {
}
/**
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.
Using the `CoreStoreDefaults.dataStack`, 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...) {
public static func monitorSectionedList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: FetchClause...) {
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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]) {
public static func monitorSectionedList<O>(createAsynchronously: @escaping (ListMonitor<O>) -> Void, _ from: From<O>, _ sectionBy: SectionBy<O>, _ fetchClauses: [FetchClause]) {
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
CoreStoreDefaults.dataStack.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(
dataStack.monitorSectionedList(
createAsynchronously: { (monitor) in
self.monitor = monitor
},
@@ -225,7 +226,7 @@ extension CoreStore {
*/
public static func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
self.defaultStack.monitorSectionedList(
CoreStoreDefaults.dataStack.monitorSectionedList(
createAsynchronously: createAsynchronously,
clauseChain.from,
clauseChain.sectionBy,

View File

@@ -29,82 +29,83 @@ import CoreData
// MARK: - CoreStore
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
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.
Using the `CoreStoreDefaults.dataStack`, 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? {
public static func fetchExisting<O: DynamicObject>(_ object: O) -> O? {
return self.defaultStack.fetchExisting(object)
return CoreStoreDefaults.dataStack.fetchExisting(object)
}
/**
Using the `defaultStack`, fetches the `DynamicObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
Using the `CoreStoreDefaults.dataStack`, 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? {
public static func fetchExisting<O: DynamicObject>(_ objectID: NSManagedObjectID) -> O? {
return self.defaultStack.fetchExisting(objectID)
return CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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 {
public static func fetchExisting<O: DynamicObject, S: Sequence>(_ objects: S) -> [O] where S.Iterator.Element == O {
return self.defaultStack.fetchExisting(objects)
return CoreStoreDefaults.dataStack.fetchExisting(objects)
}
/**
Using the `defaultStack`, fetches the `DynamicObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
Using the `CoreStoreDefaults.dataStack`, 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 {
public static func fetchExisting<O: DynamicObject, S: Sequence>(_ objectIDs: S) -> [O] where S.Iterator.Element == NSManagedObjectID {
return self.defaultStack.fetchExisting(objectIDs)
return CoreStoreDefaults.dataStack.fetchExisting(objectIDs)
}
/**
Using the `defaultStack`, fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchOne<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> D? {
public static func fetchOne<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> O? {
return try self.defaultStack.fetchOne(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchOne(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchOne<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> D? {
public static func fetchOne<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> O? {
return try self.defaultStack.fetchOne(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchOne(from, fetchClauses)
}
/**
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeen = CoreStore.fetchOne(
let youngestTeen = dataStack.fetchOne(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
@@ -116,39 +117,39 @@ extension CoreStore {
*/
public static func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> B.ObjectType? {
return try self.defaultStack.fetchOne(clauseChain)
return try CoreStoreDefaults.dataStack.fetchOne(clauseChain)
}
/**
Using the `defaultStack`, fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchAll<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> [D] {
public static func fetchAll<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [O] {
return try self.defaultStack.fetchAll(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchAll(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchAll<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> [D] {
public static func fetchAll<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [O] {
return try self.defaultStack.fetchAll(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchAll(from, fetchClauses)
}
/**
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let people = CoreStore.fetchAll(
let people = dataStack.fetchAll(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
@@ -160,39 +161,39 @@ extension CoreStore {
*/
public static func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [B.ObjectType] {
return try self.defaultStack.fetchAll(clauseChain)
return try CoreStoreDefaults.dataStack.fetchAll(clauseChain)
}
/**
Using the `defaultStack`, fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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 of `DynamicObject`s that satisfy the specified `FetchClause`s
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchCount<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> Int {
public static func fetchCount<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> Int {
return try self.defaultStack.fetchCount(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchCount(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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 of `DynamicObject`s that satisfy the specified `FetchClause`s
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchCount<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> Int {
public static func fetchCount<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> Int {
return try self.defaultStack.fetchCount(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchCount(from, fetchClauses)
}
/**
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let numberOfAdults = CoreStore.fetchCount(
let numberOfAdults = dataStack.fetchCount(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
@@ -204,39 +205,39 @@ extension CoreStore {
*/
public static func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> Int {
return try self.defaultStack.fetchCount(clauseChain)
return try CoreStoreDefaults.dataStack.fetchCount(clauseChain)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
public static func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> NSManagedObjectID? {
return try self.defaultStack.fetchObjectID(from, fetchClauses)
return try CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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, or `nil` if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
public static func fetchObjectID<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> NSManagedObjectID? {
return try self.defaultStack.fetchObjectID(from, fetchClauses)
return try CoreStoreDefaults.dataStack.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(
let youngestTeenID = dataStack.fetchObjectID(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
@@ -248,33 +249,33 @@ extension CoreStore {
*/
public static func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> NSManagedObjectID? {
return try self.defaultStack.fetchObjectID(clauseChain)
return try CoreStoreDefaults.dataStack.fetchObjectID(clauseChain)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `CoreStoreDefaults.dataStack`, 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, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
public static func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: FetchClause...) throws -> [NSManagedObjectID] {
return try self.defaultStack.fetchObjectIDs(from, fetchClauses)
return try CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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, or an empty array if no match was found
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
public static func fetchObjectIDs<O>(_ from: From<O>, _ fetchClauses: [FetchClause]) throws -> [NSManagedObjectID] {
return try self.defaultStack.fetchObjectIDs(from, fetchClauses)
return try CoreStoreDefaults.dataStack.fetchObjectIDs(from, fetchClauses)
}
/**
@@ -292,11 +293,11 @@ extension CoreStore {
*/
public static func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) throws -> [NSManagedObjectID] {
return try self.defaultStack.fetchObjectIDs(clauseChain)
return try CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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.
@@ -306,13 +307,13 @@ extension CoreStore {
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) throws -> U? {
public static func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: QueryClause...) throws -> U? {
return try self.defaultStack.queryValue(from, selectClause, queryClauses)
return try CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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.
@@ -322,9 +323,9 @@ extension CoreStore {
- returns: the result of the the query, or `nil` if no match was found. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) throws -> U? {
public static func queryValue<O, U: QueryableAttributeType>(_ from: From<O>, _ selectClause: Select<O, U>, _ queryClauses: [QueryClause]) throws -> U? {
return try self.defaultStack.queryValue(from, selectClause, queryClauses)
return try CoreStoreDefaults.dataStack.queryValue(from, selectClause, queryClauses)
}
/**
@@ -332,7 +333,7 @@ extension CoreStore {
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(
let averageAdultAge = dataStack.queryValue(
From<MyPersonEntity>()
.select(Int.self, .average(\.age))
.where(\.age > 18)
@@ -344,11 +345,11 @@ extension CoreStore {
*/
public static func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> B.ResultType? where B.ResultType: QueryableAttributeType {
return try self.defaultStack.queryValue(clauseChain)
return try CoreStoreDefaults.dataStack.queryValue(clauseChain)
}
/**
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.
Using the `CoreStoreDefaults.dataStack`, 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.
@@ -358,13 +359,13 @@ extension CoreStore {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
public static func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: QueryClause...) throws -> [[String: Any]] {
return try self.defaultStack.queryAttributes(from, selectClause, queryClauses)
return try CoreStoreDefaults.dataStack.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.
Using the `CoreStoreDefaults.dataStack`, 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.
@@ -374,9 +375,9 @@ extension CoreStore {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
- throws: `CoreStoreError.persistentStoreNotFound` if the specified entity could not be found in any store's schema.
*/
public static func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
public static func queryAttributes<O>(_ from: From<O>, _ selectClause: Select<O, NSDictionary>, _ queryClauses: [QueryClause]) throws -> [[String: Any]] {
return try self.defaultStack.queryAttributes(from, selectClause, queryClauses)
return try CoreStoreDefaults.dataStack.queryAttributes(from, selectClause, queryClauses)
}
/**
@@ -384,7 +385,7 @@ extension CoreStore {
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(
let results = dataStack.queryAttributes(
From<MyPersonEntity>()
.select(
NSDictionary.self,
@@ -405,6 +406,6 @@ extension CoreStore {
*/
public static func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) throws -> [[String: Any]] where B.ResultType == NSDictionary {
return try self.defaultStack.queryAttributes(clauseChain)
return try CoreStoreDefaults.dataStack.queryAttributes(clauseChain)
}
}

View File

@@ -29,114 +29,89 @@ import CoreData
// MARK: - CoreStore
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
extension CoreStore {
/**
Returns the `defaultStack`'s model version. The version string is the same as the name of a version-specific .xcdatamodeld file or `CoreStoreSchema`.
Returns the `CoreStoreDefaults.dataStack`'s model version. The version string is the same as the name of a version-specific .xcdatamodeld file or `CoreStoreSchema`.
*/
public static var modelVersion: String {
return self.defaultStack.modelVersion
return CoreStoreDefaults.dataStack.modelVersion
}
/**
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
Returns the entity name-to-class type mapping from the `CoreStoreDefaults.dataStack`'s model.
*/
public static func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return self.defaultStack.entityTypesByName(for: type)
return CoreStoreDefaults.dataStack.entityTypesByName(for: type)
}
/**
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
Returns the entity name-to-class type mapping from the `CoreStoreDefaults.dataStack`'s model.
*/
public static func entityTypesByName(for type: CoreStoreObject.Type) -> [EntityName: CoreStoreObject.Type] {
return self.defaultStack.entityTypesByName(for: type)
return CoreStoreDefaults.dataStack.entityTypesByName(for: type)
}
/**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `CoreStoreDefaults.dataStack`'s model.
*/
public static func entityDescription(for type: NSManagedObject.Type) -> NSEntityDescription? {
return self.defaultStack.entityDescription(for: type)
return CoreStoreDefaults.dataStack.entityDescription(for: type)
}
/**
Returns the `NSEntityDescription` for the specified `CoreStoreObject` subclass from `defaultStack`'s model.
Returns the `NSEntityDescription` for the specified `CoreStoreObject` subclass from `CoreStoreDefaults.dataStack`'s model.
*/
public static func entityDescription(for type: CoreStoreObject.Type) -> NSEntityDescription? {
return self.defaultStack.entityDescription(for: type)
return CoreStoreDefaults.dataStack.entityDescription(for: type)
}
/**
Creates an `SQLiteStore` with default parameters and adds it to the `defaultStack`. This method blocks until completion.
Creates an `SQLiteStore` with default parameters and adds it to the `CoreStoreDefaults.dataStack`. This method blocks until completion.
```
try CoreStore.addStorageAndWait()
```
- returns: the local SQLite storage added to the `defaultStack`
- returns: the local SQLite storage added to the `CoreStoreDefaults.dataStack`
*/
@discardableResult
public static func addStorageAndWait() throws -> SQLiteStore {
return try self.defaultStack.addStorageAndWait(SQLiteStore())
return try CoreStoreDefaults.dataStack.addStorageAndWait(SQLiteStore())
}
/**
Adds a `StorageInterface` to the `defaultStack` and blocks until completion.
Adds a `StorageInterface` to the `CoreStoreDefaults.dataStack` and blocks until completion.
```
try CoreStore.addStorageAndWait(InMemoryStore(configuration: "Config1"))
```
- parameter storage: the `StorageInterface`
- throws: a `CoreStoreError` value indicating the failure
- returns: the `StorageInterface` added to the `defaultStack`
- returns: the `StorageInterface` added to the `CoreStoreDefaults.dataStack`
*/
@discardableResult
public static func addStorageAndWait<T: StorageInterface>(_ storage: T) throws -> T {
return try self.defaultStack.addStorageAndWait(storage)
return try CoreStoreDefaults.dataStack.addStorageAndWait(storage)
}
/**
Adds a `LocalStorage` to the `defaultStack` and blocks until completion.
Adds a `LocalStorage` to the `CoreStoreDefaults.dataStack` and blocks until completion.
```
try CoreStore.addStorageAndWait(SQLiteStore(configuration: "Config1"))
```
- parameter storage: the local storage
- throws: a `CoreStoreError` value indicating the failure
- returns: the local storage added to the `defaultStack`. Note that this may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
- returns: the local storage added to the `CoreStoreDefaults.dataStack`. Note that this may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
*/
@discardableResult
public static func addStorageAndWait<T: LocalStorage>(_ storage: T) throws -> T {
return try self.defaultStack.addStorageAndWait(storage)
}
/**
Adds a `CloudStorage` to the `defaultStack` and blocks until completion.
```
guard let storage = ICloudStore(
ubiquitousContentName: "MyAppCloudData",
ubiquitousContentTransactionLogsSubdirectory: "logs/config1",
ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
configuration: "Config1",
cloudStorageOptions: .recreateLocalStoreOnModelMismatch
) else {
// iCloud is not available on the device
return
}
try CoreStore.addStorageAndWait(storage)
```
- parameter storage: the local storage
- throws: a `CoreStoreError` value indicating the failure
- returns: the cloud storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
*/
@discardableResult
public static func addStorageAndWait<T: CloudStorage>(_ storage: T) throws -> T {
return try self.defaultStack.addStorageAndWait(storage)
return try CoreStoreDefaults.dataStack.addStorageAndWait(storage)
}
}

View File

@@ -28,21 +28,22 @@ import Foundation
// MARK: - CoreStore
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
extension CoreStore {
/**
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
Using the `CoreStoreDefaults.dataStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
*/
public static func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, completion: @escaping (AsynchronousDataTransaction.Result<T>) -> Void) {
self.defaultStack.perform(asynchronous: task, completion: completion)
CoreStoreDefaults.dataStack.perform(asynchronous: task, completion: completion)
}
/**
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the argument of the `success` closure. Any errors thrown from inside the `task` will be wrapped in a `CoreStoreError` and reported in the `failure` closure. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
Using the `CoreStoreDefaults.dataStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the argument of the `success` closure. Any errors thrown from inside the `task` will be wrapped in a `CoreStoreError` and reported in the `failure` closure. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter success: the closure executed after the save succeeds. The `T` argument of the closure will be the value returned from `task`.
@@ -50,11 +51,11 @@ extension CoreStore {
*/
public static func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, success: @escaping (T) -> Void, failure: @escaping (CoreStoreError) -> Void) {
self.defaultStack.perform(asynchronous: task, success: success, failure: failure)
CoreStoreDefaults.dataStack.perform(asynchronous: task, success: success, failure: failure)
}
/**
Using the `defaultStack`, performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be thrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
Using the `CoreStoreDefaults.dataStack`, performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be thrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the synchronous non-escaping closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter waitForAllObservers: When `true`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks. When `false`, this method does not wait for observers to be notified of the changes before returning. This results in lower risk for deadlocks, but the updated data may not have been propagated to the `DataStack` after returning. Defaults to `true`.
@@ -63,25 +64,25 @@ extension CoreStore {
*/
public static func perform<T>(synchronous task: ((_ transaction: SynchronousDataTransaction) throws -> T), waitForAllObservers: Bool = true) throws -> T {
return try self.defaultStack.perform(synchronous: task, waitForAllObservers: waitForAllObservers)
return try CoreStoreDefaults.dataStack.perform(synchronous: task, waitForAllObservers: waitForAllObservers)
}
/**
Using the `defaultStack`, begins a non-contiguous transaction where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
Using the `CoreStoreDefaults.dataStack`, begins a non-contiguous transaction where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
- prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
public static func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
return self.defaultStack.beginUnsafe(supportsUndo: supportsUndo)
return CoreStoreDefaults.dataStack.beginUnsafe(supportsUndo: supportsUndo)
}
/**
Refreshes all registered objects `NSManagedObject`s or `CoreStoreObject`s in the `defaultStack`.
Refreshes all registered objects `NSManagedObject`s or `CoreStoreObject`s in the `CoreStoreDefaults.dataStack`.
*/
public static func refreshAndMergeAllObjects() {
self.defaultStack.refreshAndMergeAllObjects()
CoreStoreDefaults.dataStack.refreshAndMergeAllObjects()
}
}

View File

@@ -31,39 +31,20 @@ import CoreData
/**
`CoreStore` is the main entry point for all other APIs.
*/
@available(*, deprecated, message: "Call methods directly from the DataStack instead")
public enum CoreStore {
/**
The default `DataStack` instance to be used. If `defaultStack` is not set before the first time accessed, a default-configured `DataStack` will be created.
- SeeAlso: `DataStack`
- Note: Changing the `defaultStack` is thread safe, but it is recommended to setup `DataStacks` on a common queue (e.g. the main queue).
*/
@available(*, unavailable, renamed: "CoreStoreDefaults.logger")
public static var logger: CoreStoreLogger {
get { return CoreStoreDefaults.logger }
set { CoreStoreDefaults.logger = newValue }
}
@available(*, unavailable, renamed: "CoreStoreDefaults.dataStack")
public static var defaultStack: DataStack {
get {
self.defaultStackBarrierQueue.sync(flags: .barrier) {
if self.defaultStackInstance == nil {
self.defaultStackInstance = DataStack()
}
}
return self.defaultStackInstance!
}
set {
self.defaultStackBarrierQueue.async(flags: .barrier) {
self.defaultStackInstance = newValue
}
}
get { return CoreStoreDefaults.dataStack }
set { CoreStoreDefaults.dataStack = newValue }
}
// MARK: Private
private static let defaultStackBarrierQueue = DispatchQueue.concurrent("com.coreStore.defaultStackBarrierQueue")
private static var defaultStackInstance: DataStack?
}

View File

@@ -37,7 +37,7 @@
#error CoreStore Objective-C utilities can only be used on platforms that support C function overloading
#endif
#define CORESTORE_EXTERN extern
#define CORESTORE_EXTERN extern __deprecated_msg("CoreStore Objective-C API will be removed soon.")
#define CORESTORE_OVERLOADABLE __attribute__((__overloadable__))
#define CORESTORE_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0, 1)))
#define CORESTORE_RETURNS_RETAINED __attribute__((ns_returns_retained))

Some files were not shown because too many files have changed in this diff Show More