mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-13 04:40:32 +01:00
Compare commits
70 Commits
3.0.2
...
4.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
feb0e30735 | ||
|
|
9c25336ff6 | ||
|
|
66bef87422 | ||
|
|
dd2949ee18 | ||
|
|
e0abb9b0af | ||
|
|
42c28b064a | ||
|
|
0b097b8c85 | ||
|
|
fce5d2f301 | ||
|
|
8ff163af30 | ||
|
|
19abedfa9f | ||
|
|
48828fdca3 | ||
|
|
9d65a27557 | ||
|
|
6d04806608 | ||
|
|
54129f7362 | ||
|
|
54c81d23f5 | ||
|
|
53ab140341 | ||
|
|
9dc4331b26 | ||
|
|
e6aa72fb5f | ||
|
|
274a54451a | ||
|
|
fe70b7a27d | ||
|
|
02a660e4a6 | ||
|
|
a543a4c94a | ||
|
|
fd14a18248 | ||
|
|
b0e2655bdf | ||
|
|
b6bc7c2edf | ||
|
|
1938f0d9de | ||
|
|
94e6db669f | ||
|
|
b1972b82f1 | ||
|
|
5ffaca1375 | ||
|
|
a73306fecb | ||
|
|
9f3db61ff7 | ||
|
|
e5ef4992d3 | ||
|
|
c0ae129b22 | ||
|
|
4aa1a63f9a | ||
|
|
4fc10afe1e | ||
|
|
8b77e4e5a0 | ||
|
|
258c237100 | ||
|
|
6948db516d | ||
|
|
b5d80fd272 | ||
|
|
cdcd7d0416 | ||
|
|
a5162239d5 | ||
|
|
1ad6ac5769 | ||
|
|
ecb3d0cfa0 | ||
|
|
81355fd9c5 | ||
|
|
97d7a276fe | ||
|
|
d72d1afe8b | ||
|
|
716e069984 | ||
|
|
881ee4af0a | ||
|
|
acc0ce1c32 | ||
|
|
b97f6d6a0a | ||
|
|
818abfc1a1 | ||
|
|
f055c54a66 | ||
|
|
cb6d5b015b | ||
|
|
494965de23 | ||
|
|
fe25a9aa36 | ||
|
|
f21e4e12e0 | ||
|
|
92890d1e1d | ||
|
|
0c483e0e19 | ||
|
|
6055685c00 | ||
|
|
ee71442b08 | ||
|
|
341ec5e771 | ||
|
|
8569c3c524 | ||
|
|
3224fcf71d | ||
|
|
9ff1c9d545 | ||
|
|
c40d17a6ad | ||
|
|
9d5e04854a | ||
|
|
d2fd03c1f0 | ||
|
|
7baaee493d | ||
|
|
03973790a8 | ||
|
|
7ee027f44d |
@@ -1 +1 @@
|
||||
3.0.1
|
||||
3.1
|
||||
|
||||
31
.travis.yml
31
.travis.yml
@@ -1,5 +1,5 @@
|
||||
language: objective-c
|
||||
osx_image: xcode8.2
|
||||
osx_image: xcode8.3
|
||||
sudo: false
|
||||
git:
|
||||
submodules: false
|
||||
@@ -9,22 +9,23 @@ env:
|
||||
global:
|
||||
- LC_CTYPE=en_US.UTF-8
|
||||
- LANG=en_US.UTF-8
|
||||
matrix:
|
||||
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
matrix:
|
||||
- DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=3.1,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.1 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.1 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.1,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.1 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.1 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO"
|
||||
- DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
|
||||
before_install:
|
||||
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
|
||||
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
|
||||
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.18/Carthage.pkg"
|
||||
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.20.1/Carthage.pkg"
|
||||
- sudo installer -pkg "Carthage.pkg" -target /
|
||||
- rm "Carthage.pkg"
|
||||
before_script:
|
||||
@@ -37,8 +38,8 @@ script:
|
||||
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
fi
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.2" -destination "OS=10.1,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.2" -destination "OS=10.1,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
|
||||
- if [ $POD_LINT == "YES" ]; then
|
||||
pod lib lint --quick;
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CoreStore"
|
||||
s.version = "3.0.2"
|
||||
s.version = "4.0.0-beta"
|
||||
s.license = "MIT"
|
||||
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
|
||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||
@@ -16,7 +16,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 USE_FRAMEWORKS -D DEBUG',
|
||||
'OTHER_SWIFT_FLAGS[config=Release]' => '-D USE_FRAMEWORKS',
|
||||
'GCC_PREPROCESSOR_DEFINITIONS' => 'USE_FRAMEWORKS=1' }
|
||||
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG' }
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -63,6 +63,11 @@
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
<AdditionalOption
|
||||
key = "NSZombieEnabled"
|
||||
value = "YES"
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
|
||||
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */; };
|
||||
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */; };
|
||||
B5125C141B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */; };
|
||||
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977D81B120B80003D50A5 /* ObserversViewController.swift */; };
|
||||
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */; };
|
||||
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977DE1B120F83003D50A5 /* MapKit.framework */; };
|
||||
@@ -331,7 +330,6 @@
|
||||
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
|
||||
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
|
||||
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
|
||||
B5125C141B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel in Sources */,
|
||||
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
|
||||
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
|
||||
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
|
||||
@@ -378,8 +376,10 @@
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
@@ -423,8 +423,10 @@
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
import CoreStore
|
||||
|
||||
// MARK: - AppDelegate
|
||||
|
||||
@@ -18,10 +19,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
|
||||
|
||||
application.statusBarStyle = .lightContent
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10112" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ni8-QF-XHB">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12113" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10083"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12078"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<customFonts key="customFonts">
|
||||
<mutableArray key="AppleSDGothicNeo.ttc">
|
||||
<array key="AppleSDGothicNeo.ttc">
|
||||
<string>AppleSDGothicNeo-Regular</string>
|
||||
</mutableArray>
|
||||
<mutableArray key="HelveticaNeue.ttc">
|
||||
<string>HelveticaNeue-Bold</string>
|
||||
<string>HelveticaNeue-Bold</string>
|
||||
</array>
|
||||
<array key="HelveticaNeue.ttc">
|
||||
<string>HelveticaNeue</string>
|
||||
<string>HelveticaNeue</string>
|
||||
</mutableArray>
|
||||
<mutableArray key="HelveticaNeueLights.ttc">
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Bold</string>
|
||||
</array>
|
||||
<array key="HelveticaNeueLights.ttc">
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Thin</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
<string>HelveticaNeue-Light</string>
|
||||
</mutableArray>
|
||||
</array>
|
||||
</customFonts>
|
||||
<scenes>
|
||||
<!--SNS Accounts-->
|
||||
@@ -41,34 +30,34 @@
|
||||
<objects>
|
||||
<tableViewController id="AW4-lY-JNk" customClass="StackSetupDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="S3A-lm-AuA">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="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="yud-WH-MPa">
|
||||
<rect key="frame" x="0.0" y="64" width="600" height="150"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="150"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sns" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="czc-nd-es9">
|
||||
<rect key="frame" x="20" y="20" width="560" height="26.5"/>
|
||||
<rect key="frame" x="20" y="20" width="335" height="26.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="name" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1eh-91-O2N">
|
||||
<rect key="frame" x="20" y="70" width="41" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="friends" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p2y-0T-hQs">
|
||||
<rect key="frame" x="539.5" y="72" width="40.5" height="17"/>
|
||||
<rect key="frame" x="314.5" y="72" width="40.5" height="17"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="14"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.20392156862745098" green="0.28627450980392155" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="1eh-91-O2N" firstAttribute="top" secondItem="czc-nd-es9" secondAttribute="bottom" constant="23.5" id="F6q-Jt-glI"/>
|
||||
<constraint firstItem="p2y-0T-hQs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="1eh-91-O2N" secondAttribute="trailing" constant="20" id="GVS-6o-rmj"/>
|
||||
@@ -82,24 +71,24 @@
|
||||
</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="236" width="600" height="44"/>
|
||||
<rect key="frame" x="0.0" y="172" 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="600" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq">
|
||||
<rect key="frame" x="15" y="13" width="28.5" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hR1-Zb-BOk">
|
||||
<rect key="frame" x="533" y="13" width="52" height="19"/>
|
||||
<rect key="frame" x="308" y="13" width="52" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
|
||||
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -131,23 +120,23 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="t9A-zf-Iew"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="75P-2m-6cr">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<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="600" height="276"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<rect key="frame" x="0.0" y="324" width="375" height="343"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="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="600" height="44"/>
|
||||
<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="WVb-th-o8c" id="JBq-Ml-a9p">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OQf-Bd-Zze">
|
||||
<rect key="frame" x="520" y="8" width="72" height="27.5"/>
|
||||
<rect key="frame" x="295" y="8" width="72" height="27.5"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<inset key="contentEdgeInsets" minX="7" minY="0.0" maxX="7" maxY="0.0"/>
|
||||
<state key="normal" title="mutate!"/>
|
||||
@@ -156,9 +145,9 @@
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VZk-6K-4ut">
|
||||
<rect key="frame" x="15" y="8" width="495" height="27.5"/>
|
||||
<rect key="frame" x="15" y="8" width="270" height="27.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="17"/>
|
||||
<color key="textColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -184,42 +173,42 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XKA-Ub-c2X">
|
||||
<rect key="frame" x="0.0" y="64" width="600" height="260"/>
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="260"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i7U-bW-juB" customClass="UIButton">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="260"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="260"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Organism" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zxy-nY-P44">
|
||||
<rect key="frame" x="20" y="90.5" width="560" height="26.5"/>
|
||||
<rect key="frame" x="20" y="90.5" width="335" height="26.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="560" height="20.5"/>
|
||||
<rect key="frame" x="20" y="131.5" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="560" height="29"/>
|
||||
<rect key="frame" x="20" y="20" width="335" height="29"/>
|
||||
<segments>
|
||||
<segment title="First"/>
|
||||
<segment title="Second"/>
|
||||
<segment title=""/>
|
||||
</segments>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="segmentedControlValueChanged:" destination="iVv-Vc-nCL" eventType="valueChanged" id="RwG-kW-RPg"/>
|
||||
</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="560" height="2"/>
|
||||
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="trackTintColor" white="1" alpha="0.20000000000000001" colorSpace="calibratedWhite"/>
|
||||
<rect key="frame" x="20" y="68" 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>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="zxy-nY-P44" firstAttribute="leading" secondItem="i7U-bW-juB" secondAttribute="leading" constant="20" id="1u1-Tq-hRn"/>
|
||||
<constraint firstItem="6Ac-xl-ldZ" firstAttribute="top" secondItem="zxy-nY-P44" secondAttribute="bottom" constant="14.5" id="39B-9l-O3g"/>
|
||||
@@ -237,7 +226,7 @@
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="260" id="90R-Mf-iAB"/>
|
||||
<constraint firstItem="i7U-bW-juB" firstAttribute="leading" secondItem="XKA-Ub-c2X" secondAttribute="leading" id="e9h-f4-c37"/>
|
||||
@@ -246,7 +235,7 @@
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="XKA-Ub-c2X" secondAttribute="trailing" id="U0P-51-KT9"/>
|
||||
<constraint firstAttribute="trailing" secondItem="WUc-3Y-Quw" secondAttribute="trailing" id="i7I-7B-97K"/>
|
||||
@@ -276,31 +265,31 @@
|
||||
<objects>
|
||||
<tableViewController id="t0d-B0-B7U" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="50" sectionHeaderHeight="10" sectionFooterHeight="10" id="uHB-Yr-ujV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<sections>
|
||||
<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="99" width="600" height="50"/>
|
||||
<rect key="frame" x="0.0" y="35" 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="567" height="49.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||
<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="15" y="6" 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.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="30" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -310,24 +299,24 @@
|
||||
</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="149" width="600" height="50"/>
|
||||
<rect key="frame" x="0.0" y="85" 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="567" height="49.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||
<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="15" y="6" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="30" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -337,24 +326,24 @@
|
||||
</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="199" width="600" height="50"/>
|
||||
<rect key="frame" x="0.0" y="135" 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="567" height="49.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||
<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="15" y="6" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="30" width="179" height="13.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -364,24 +353,24 @@
|
||||
</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="249" width="600" height="50"/>
|
||||
<rect key="frame" x="0.0" y="185" 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="567" height="49.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||
<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="15" y="6" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="30" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -391,24 +380,24 @@
|
||||
</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="299" width="600" height="50"/>
|
||||
<rect key="frame" x="0.0" y="235" 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="567" height="49.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||
<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="15" y="6" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="30" width="159" height="13.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -418,24 +407,24 @@
|
||||
</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="349" width="600" height="50"/>
|
||||
<rect key="frame" x="0.0" y="285" 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="567" height="49.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
|
||||
<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="15" y="6" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="30" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -467,69 +456,69 @@
|
||||
<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="592" height="268"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
|
||||
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
|
||||
<rect key="frame" x="20" y="69.5" width="552" height="36.5"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<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="20" y="116" width="552" height="18"/>
|
||||
<rect key="frame" x="16" y="149.5" width="343" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="20" y="154" width="74" height="18"/>
|
||||
<rect key="frame" x="16" y="187.5" width="74" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="20" y="192" width="74" height="18"/>
|
||||
<rect key="frame" x="16" y="225.5" width="74" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="20" y="230" width="74" height="18"/>
|
||||
<rect key="frame" x="16" y="263.5" width="74" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="102" y="148" width="472" height="31"/>
|
||||
<rect key="frame" x="98" y="181.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="102" y="186" width="472" height="31"/>
|
||||
<rect key="frame" x="98" y="219.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="102" y="224" width="472" height="31"/>
|
||||
<rect key="frame" x="98" y="257.5" width="263" height="31"/>
|
||||
<connections>
|
||||
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
|
||||
<rect key="frame" x="20" y="49" width="552" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="p4O-tf-dgt" firstAttribute="trailing" secondItem="w8K-eN-RvU" secondAttribute="trailingMargin" id="022-ll-1s1"/>
|
||||
<constraint firstItem="vTa-ly-eyO" firstAttribute="top" secondItem="rry-vh-bRK" secondAttribute="bottom" constant="20" id="1hd-Ti-CnT"/>
|
||||
@@ -591,23 +580,23 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="LNL-mj-D7l"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="6x3-vn-Egt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
|
||||
<rect key="frame" x="4" y="64" width="592" height="268"/>
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="301.5"/>
|
||||
<connections>
|
||||
<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="4" y="332" width="592" height="268"/>
|
||||
<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>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<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"/>
|
||||
@@ -636,11 +625,11 @@
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="00L-5k-Eno">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="barTintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="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"/>
|
||||
<textAttributes key="titleTextAttributes">
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="24"/>
|
||||
<color key="textColor" red="0.92549019607843142" green="0.94117647058823528" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</textAttributes>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
@@ -657,19 +646,19 @@
|
||||
<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="592" height="268"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="301.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="66" width="592" height="44"/>
|
||||
<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="G3X-70-BCD" id="aT8-nz-i5l">
|
||||
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF">
|
||||
<rect key="frame" x="8" y="8" width="27" height="27"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="uQX-PI-UWF" secondAttribute="height" multiplier="1:1" id="9qA-iN-Neb"/>
|
||||
</constraints>
|
||||
@@ -677,7 +666,7 @@
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HJC-5w-lIN">
|
||||
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -716,20 +705,20 @@
|
||||
<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="592" height="268"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<prototypes>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="zSO-3e-OVq" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
|
||||
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zSO-3e-OVq" id="cHA-by-n4b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH">
|
||||
<rect key="frame" x="8" y="8" width="27" height="27"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="5uq-Yi-XwH" secondAttribute="height" multiplier="1:1" id="oOe-HC-VyN"/>
|
||||
</constraints>
|
||||
@@ -737,7 +726,7 @@
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Zyu-PC-WmO">
|
||||
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -780,11 +769,11 @@
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="6XA-6M-yvZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="barTintColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="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.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</textAttributes>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
@@ -805,17 +794,17 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="k4s-iL-Krh">
|
||||
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="536"/>
|
||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="536"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
|
||||
</connections>
|
||||
</mapView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="RZg-hi-T8O" firstAttribute="top" secondItem="V2U-0R-Ts0" secondAttribute="bottom" id="GcS-Jz-Wcm"/>
|
||||
<constraint firstItem="V2U-0R-Ts0" firstAttribute="top" secondItem="k4s-iL-Krh" secondAttribute="top" id="S5Z-Da-V6J"/>
|
||||
@@ -842,30 +831,30 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="Cwn-Jd-4Lr"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="n9M-Je-Dj0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<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="600" height="458"/>
|
||||
<color key="backgroundColor" red="0.20392156862745098" green="0.28627450980392155" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.94509803921568625" green="0.7686274509803922" blue="0.058823529411764705" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<rect key="frame" x="0.0" y="142" width="375" height="525"/>
|
||||
<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="560" height="29"/>
|
||||
<rect key="frame" x="20" y="94" width="335" height="29"/>
|
||||
<segments>
|
||||
<segment title="Log"/>
|
||||
<segment title="Error"/>
|
||||
<segment title="Assert"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="tintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="segmentedControlValueChanged:" destination="5yy-0N-QDU" eventType="valueChanged" id="2pp-Vt-2Os"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="4iq-B4-k0p" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" constant="20" id="6SM-eN-NxP"/>
|
||||
<constraint firstItem="TpK-gX-CTN" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" id="AAw-IG-taz"/>
|
||||
@@ -901,11 +890,11 @@
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wJo-mp-1pS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.74117647058823533" green="0.76470588235294112" blue="0.7803921568627451" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="barTintColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="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.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</textAttributes>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
@@ -926,15 +915,15 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="DlN-cN-JXd"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="eC3-ql-d2o">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<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="600" height="536"/>
|
||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
|
||||
<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">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="80"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="80"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="YVj-dA-fyV">
|
||||
@@ -943,13 +932,13 @@
|
||||
<segment title="Fetch"/>
|
||||
<segment title="Query"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="tintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="segmentedControlValueChanged:" destination="qbj-MK-nIY" eventType="valueChanged" id="Wok-dl-uq7"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="0.80000000000000004" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="YVj-dA-fyV" firstAttribute="leading" secondItem="iaH-1W-Sbo" secondAttribute="leading" constant="20" id="1dX-t7-dyR"/>
|
||||
<constraint firstAttribute="centerY" secondItem="YVj-dA-fyV" secondAttribute="centerY" id="HXU-Z7-jfu"/>
|
||||
@@ -958,17 +947,17 @@
|
||||
</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="600" height="44"/>
|
||||
<rect key="frame" x="0.0" y="102" 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="567" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||
<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="550" height="43.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -981,7 +970,7 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="WGY-kX-mAx" firstAttribute="top" secondItem="dgu-PC-LiB" secondAttribute="bottom" id="0pS-cU-ibk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="WGY-kX-mAx" secondAttribute="trailing" id="NeY-g5-CaB"/>
|
||||
@@ -1006,30 +995,30 @@
|
||||
<objects>
|
||||
<tableViewController id="tIs-pN-OgO" customClass="FetchingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="tVl-tT-UDk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="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"/>
|
||||
<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="100" width="600" height="60"/>
|
||||
<rect key="frame" x="0.0" y="36" 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="600" height="59.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/>
|
||||
<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="15" y="11" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="35" width="31" height="13.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
@@ -1052,30 +1041,30 @@
|
||||
<objects>
|
||||
<tableViewController id="o9D-Xm-13g" customClass="QueryingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="bMh-zR-xwu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="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"/>
|
||||
<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="100" width="600" height="60"/>
|
||||
<rect key="frame" x="0.0" y="36" 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="600" height="59.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/>
|
||||
<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="15" y="11" 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.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</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="15" y="35" width="31" height="13.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
|
||||
@@ -22,26 +22,24 @@ private struct Static {
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
)
|
||||
|
||||
_ = dataStack.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
transaction.deleteAll(From<TimeZone>())
|
||||
|
||||
for name in NSTimeZone.knownTimeZoneNames {
|
||||
_ = try? dataStack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let rawTimeZone = NSTimeZone(name: name)!
|
||||
let cachedTimeZone = transaction.create(Into<TimeZone>())
|
||||
transaction.deleteAll(From<TimeZone>())
|
||||
|
||||
cachedTimeZone.name = rawTimeZone.name
|
||||
cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? ""
|
||||
cachedTimeZone.secondsFromGMT = Int32(rawTimeZone.secondsFromGMT)
|
||||
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
|
||||
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
|
||||
for name in NSTimeZone.knownTimeZoneNames {
|
||||
|
||||
let rawTimeZone = NSTimeZone(name: name)!
|
||||
let cachedTimeZone = transaction.create(Into<TimeZone>())
|
||||
|
||||
cachedTimeZone.name = rawTimeZone.name
|
||||
cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? ""
|
||||
cachedTimeZone.secondsFromGMT = Int32(rawTimeZone.secondsFromGMT)
|
||||
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
|
||||
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
|
||||
}
|
||||
}
|
||||
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
|
||||
)
|
||||
return dataStack
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -43,7 +43,10 @@ private struct Static {
|
||||
|
||||
didSet {
|
||||
|
||||
self.palettes.refetch(self.filter.whereClause())
|
||||
self.palettes.refetch(
|
||||
self.filter.whereClause(),
|
||||
OrderBy(.ascending(#keyPath(Palette.hue)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,11 +175,13 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
case .delete:
|
||||
let palette = Static.palettes[indexPath]
|
||||
CoreStore.beginAsynchronous{ (transaction) -> Void in
|
||||
|
||||
transaction.delete(palette)
|
||||
transaction.commit { (result) -> Void in }
|
||||
}
|
||||
CoreStore.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
transaction.delete(palette)
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
|
||||
default:
|
||||
break
|
||||
@@ -263,11 +268,13 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
transaction.deleteAll(From<Palette>())
|
||||
transaction.commit()
|
||||
}
|
||||
CoreStore.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
transaction.deleteAll(From<Palette>())
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
@@ -277,13 +284,14 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
let palette = transaction.create(Into<Palette>())
|
||||
palette.setInitialValues()
|
||||
|
||||
transaction.commit()
|
||||
}
|
||||
CoreStore.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let palette = transaction.create(Into<Palette>())
|
||||
palette.setInitialValues()
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
private func setTable(enabled: Bool) {
|
||||
|
||||
@@ -56,13 +56,13 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
}
|
||||
else {
|
||||
|
||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let palette = transaction.create(Into(Palette.self))
|
||||
palette.setInitialValues()
|
||||
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
_ = try? CoreStore.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let palette = transaction.create(Into(Palette.self))
|
||||
palette.setInitialValues()
|
||||
}
|
||||
)
|
||||
|
||||
let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue))))!
|
||||
self.monitor = CoreStore.monitorObject(palette)
|
||||
@@ -121,49 +121,57 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let hue = self.hueSlider?.value ?? 0
|
||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
CoreStore.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
palette.hue = Int32(hue)
|
||||
transaction.commit()
|
||||
}
|
||||
}
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.hue = Int32(hue)
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let saturation = self.saturationSlider?.value ?? 0
|
||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
CoreStore.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
palette.saturation = saturation
|
||||
transaction.commit()
|
||||
}
|
||||
}
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.saturation = saturation
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
|
||||
|
||||
let brightness = self.brightnessSlider?.value ?? 0
|
||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
||||
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
CoreStore.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
palette.brightness = brightness
|
||||
transaction.commit()
|
||||
}
|
||||
}
|
||||
if let palette = transaction.edit(self?.monitor?.object) {
|
||||
|
||||
palette.brightness = brightness
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
|
||||
|
||||
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
|
||||
|
||||
transaction.delete(self?.monitor?.object)
|
||||
transaction.commit()
|
||||
}
|
||||
CoreStore.perform(
|
||||
asynchronous: { [weak self] (transaction) in
|
||||
|
||||
transaction.delete(self?.monitor?.object)
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
|
||||
|
||||
@@ -25,7 +25,7 @@ class Palette: NSManagedObject {
|
||||
get {
|
||||
|
||||
let KVCKey = #keyPath(Palette.colorName)
|
||||
if let colorName = self.accessValueForKVCKey(KVCKey) as? String {
|
||||
if let colorName = self.getValue(forKvcKey: KVCKey) as? String {
|
||||
|
||||
return colorName
|
||||
}
|
||||
@@ -49,7 +49,7 @@ class Palette: NSManagedObject {
|
||||
}
|
||||
set {
|
||||
|
||||
self.setValue(newValue, forKVCKey: #keyPath(Palette.colorName))
|
||||
self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,10 +98,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
switch self.segmentedControl?.selectedSegmentIndex {
|
||||
|
||||
case 0?:
|
||||
self.dataStack.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
_ = transaction.create(Into<Palette>())
|
||||
}
|
||||
let request = NSFetchRequest<NSFetchRequestResult>()
|
||||
Where(true).applyToFetchRequest(request)
|
||||
Where(false).applyToFetchRequest(request)
|
||||
|
||||
case 1?:
|
||||
_ = try? dataStack.addStorageAndWait(
|
||||
@@ -112,10 +111,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
)
|
||||
|
||||
case 2?:
|
||||
self.dataStack.beginAsynchronous { (transaction) -> Void in
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
|
||||
transaction.commit()
|
||||
transaction.commit()
|
||||
_ = self.dataStack.fetchOne(From<Palette>())
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -60,7 +60,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
}
|
||||
for model in models {
|
||||
|
||||
if model.version == storeVersion {
|
||||
if model.schemaHistory.currentModelVersion == storeVersion {
|
||||
|
||||
return model
|
||||
}
|
||||
@@ -115,16 +115,17 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
|
||||
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
|
||||
self.setEnabled(false)
|
||||
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in
|
||||
|
||||
let organism = transaction.edit(organism) as! OrganismProtocol
|
||||
organism.mutate()
|
||||
|
||||
transaction.commit { _ -> Void in
|
||||
dataStack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let organism = transaction.edit(organism) as! OrganismProtocol
|
||||
organism.mutate()
|
||||
},
|
||||
completion: { [weak self] _ in
|
||||
|
||||
self?.setEnabled(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
return cell
|
||||
}
|
||||
@@ -140,29 +141,35 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private typealias ModelMetadata = (label: String, version: String, entityType: AnyClass, migrationChain: MigrationChain)
|
||||
private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
|
||||
|
||||
private let models: [ModelMetadata] = [
|
||||
(
|
||||
label: "Model V1",
|
||||
version: "MigrationDemo",
|
||||
entityType: OrganismV1.self,
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
)
|
||||
),
|
||||
(
|
||||
label: "Model V2",
|
||||
version: "MigrationDemoV2",
|
||||
entityType: OrganismV2.self,
|
||||
migrationChain: [
|
||||
"MigrationDemo": "MigrationDemoV2",
|
||||
"MigrationDemoV3": "MigrationDemoV2"
|
||||
]
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: [
|
||||
"MigrationDemo": "MigrationDemoV2",
|
||||
"MigrationDemoV3": "MigrationDemoV2"
|
||||
]
|
||||
)
|
||||
),
|
||||
(
|
||||
label: "Model V3",
|
||||
version: "MigrationDemoV3",
|
||||
entityType: OrganismV3.self,
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
schemaHistory: SchemaHistory(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
@@ -209,21 +216,44 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
|
||||
private func selectModelVersion(_ model: ModelMetadata) {
|
||||
|
||||
if self.dataStack?.modelVersion == model.version {
|
||||
if self.dataStack?.modelVersion == model.schemaHistory.currentModelVersion {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
|
||||
|
||||
let dataStack = DataStack(
|
||||
modelName: "MigrationDemo",
|
||||
migrationChain: model.migrationChain
|
||||
)
|
||||
let dataStack = DataStack(schemaHistory: model.schemaHistory)
|
||||
|
||||
self.setEnabled(false)
|
||||
let progress = dataStack.addStorage(
|
||||
SQLiteStore(fileName: "MigrationDemo.sqlite"),
|
||||
SQLiteStore(
|
||||
fileName: "MigrationDemo.sqlite",
|
||||
migrationMappingProviders: [
|
||||
CustomSchemaMappingProvider(
|
||||
from: "MigrationDemoV3",
|
||||
to: "MigrationDemoV2",
|
||||
entityMappings: [
|
||||
.transformEntity(
|
||||
sourceEntity: "Organism",
|
||||
destinationEntity: "Organism",
|
||||
transformer: { (source, createDestination) in
|
||||
|
||||
let destination = createDestination()
|
||||
destination.enumerateAttributes { (attribute, sourceAttribute) in
|
||||
|
||||
if let sourceAttribute = sourceAttribute {
|
||||
|
||||
destination[attribute] = source[sourceAttribute]
|
||||
}
|
||||
}
|
||||
destination["numberOfFlippers"] = source["numberOfLimbs"]
|
||||
}
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
completion: { [weak self] (result) -> Void in
|
||||
|
||||
guard let `self` = self else {
|
||||
@@ -250,25 +280,26 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
|
||||
for i: Int64 in 0 ..< 20 {
|
||||
|
||||
dataStack.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
for j: Int64 in 0 ..< 500 {
|
||||
dataStack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let organism = transaction.create(Into(model.entityType)) as! OrganismProtocol
|
||||
organism.dna = (i * 500) + j + 1
|
||||
organism.mutate()
|
||||
}
|
||||
|
||||
transaction.commit()
|
||||
}
|
||||
for j: Int64 in 0 ..< 500 {
|
||||
|
||||
let organism = transaction.create(Into(model.entityType)) as! OrganismProtocol
|
||||
organism.dna = (i * 500) + j + 1
|
||||
organism.mutate()
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in
|
||||
|
||||
transaction.commit { _ in
|
||||
|
||||
dataStack.perform(
|
||||
asynchronous: { _ in },
|
||||
completion: { [weak self] _ in
|
||||
|
||||
self?.setEnabled(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -311,7 +342,13 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
|
||||
|
||||
if let dataStack = dataStack, let model = model {
|
||||
|
||||
self.segmentedControl?.selectedSegmentIndex = self.models.map { $0.version }.index(of: model.version)!
|
||||
self.segmentedControl?.selectedSegmentIndex = self.models
|
||||
.index(
|
||||
where: { (_, _, schemaHistory) -> Bool in
|
||||
|
||||
schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
|
||||
}
|
||||
)!
|
||||
|
||||
self._dataStack = dataStack
|
||||
let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna")))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE database SYSTEM "file:///System/Library/DTDs/CoreData.dtd">
|
||||
|
||||
<database>
|
||||
@@ -10,7 +10,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPersistenceFrameworkVersion</key>
|
||||
<integer>526</integer>
|
||||
<integer>754</integer>
|
||||
<key>NSStoreModelVersionHashes</key>
|
||||
<dict>
|
||||
<key>XDDevAttributeMapping</key>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16E195" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES">
|
||||
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="hasVertebrae" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" elementID="numberOfFlippers" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="Organism" positionX="-36" positionY="9" width="128" height="120"/>
|
||||
|
||||
@@ -33,22 +33,22 @@ private struct Static {
|
||||
)
|
||||
)
|
||||
|
||||
_ = dataStack.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
transaction.deleteAll(From<UserAccount>())
|
||||
|
||||
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
|
||||
account1.accountType = "Facebook"
|
||||
account1.name = "John Smith HCD"
|
||||
account1.friends = 42
|
||||
|
||||
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
|
||||
account2.accountType = "Facebook"
|
||||
account2.name = "Jane Doe HCD"
|
||||
account2.friends = 314
|
||||
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
_ = try? dataStack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
transaction.deleteAll(From<UserAccount>())
|
||||
|
||||
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
|
||||
account1.accountType = "Facebook"
|
||||
account1.name = "John Smith HCD"
|
||||
account1.friends = 42
|
||||
|
||||
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
|
||||
account2.accountType = "Facebook"
|
||||
account2.name = "Jane Doe HCD"
|
||||
account2.friends = 314
|
||||
}
|
||||
)
|
||||
|
||||
return dataStack
|
||||
}()
|
||||
@@ -71,23 +71,22 @@ private struct Static {
|
||||
)
|
||||
)
|
||||
|
||||
_ = dataStack.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
transaction.deleteAll(From<UserAccount>())
|
||||
|
||||
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
|
||||
account1.accountType = "Twitter"
|
||||
account1.name = "#johnsmith_hcd"
|
||||
account1.friends = 7
|
||||
|
||||
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
|
||||
account2.accountType = "Twitter"
|
||||
account2.name = "#janedoe_hcd"
|
||||
account2.friends = 100
|
||||
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
|
||||
_ = try? dataStack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
transaction.deleteAll(From<UserAccount>())
|
||||
|
||||
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
|
||||
account1.accountType = "Twitter"
|
||||
account1.name = "#johnsmith_hcd"
|
||||
account1.friends = 7
|
||||
|
||||
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
|
||||
account2.accountType = "Twitter"
|
||||
account2.name = "#janedoe_hcd"
|
||||
account2.friends = 100
|
||||
}
|
||||
)
|
||||
return dataStack
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -28,13 +28,13 @@ private struct Static {
|
||||
var place = CoreStore.fetchOne(From<Place>())
|
||||
if place == nil {
|
||||
|
||||
_ = CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let place = transaction.create(Into<Place>())
|
||||
place.setInitialValues()
|
||||
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
_ = try? CoreStore.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let place = transaction.create(Into<Place>())
|
||||
place.setInitialValues()
|
||||
}
|
||||
)
|
||||
place = CoreStore.fetchOne(From<Place>())
|
||||
}
|
||||
|
||||
@@ -169,23 +169,26 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
|
||||
gesture.location(in: mapView),
|
||||
toCoordinateFrom: mapView
|
||||
)
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
let place = transaction.edit(Static.placeController.object)
|
||||
place?.coordinate = coordinate
|
||||
transaction.commit { (_) -> Void in }
|
||||
}
|
||||
CoreStore.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let place = transaction.edit(Static.placeController.object)
|
||||
place?.coordinate = coordinate
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
|
||||
|
||||
_ = CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let place = transaction.edit(Static.placeController.object)
|
||||
place?.setInitialValues()
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
_ = try? CoreStore.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let place = transaction.edit(Static.placeController.object)
|
||||
place?.setInitialValues()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func geocode(place: Place) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class BaseTestCase: XCTestCase {
|
||||
|
||||
@nonobjc
|
||||
@discardableResult
|
||||
func prepareStack<T>(configurations: [String?] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
||||
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
|
||||
@@ -17,7 +17,7 @@ import CoreStore
|
||||
class BaseTestDataTestCase: BaseTestCase {
|
||||
|
||||
@nonobjc
|
||||
let dateFormatter: DateFormatter = {
|
||||
let dateFormatter: DateFormatter = cs_lazy {
|
||||
|
||||
let formatter = DateFormatter()
|
||||
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
@@ -25,52 +25,53 @@ class BaseTestDataTestCase: BaseTestCase {
|
||||
formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
|
||||
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
|
||||
return formatter
|
||||
}()
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
func prepareTestDataForStack(_ stack: DataStack, configurations: [String?] = [nil]) {
|
||||
func prepareTestDataForStack(_ stack: DataStack, configurations: [ModelConfiguration] = [nil]) {
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
for (configurationIndex, configuration) in configurations.enumerated() {
|
||||
try! stack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let configurationOrdinal = configurationIndex + 1
|
||||
if configuration == nil || configuration == "Config1" {
|
||||
for (configurationIndex, configuration) in configurations.enumerated() {
|
||||
|
||||
for idIndex in 1 ... 5 {
|
||||
let configurationOrdinal = configurationIndex + 1
|
||||
if configuration == nil || configuration == "Config1" {
|
||||
|
||||
let object = transaction.create(Into<TestEntity1>(configuration))
|
||||
object.testEntityID = NSNumber(value: (configurationOrdinal * 100) + idIndex)
|
||||
|
||||
object.testNumber = NSNumber(value: idIndex)
|
||||
object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
|
||||
object.testBoolean = NSNumber(value: (idIndex % 2) == 1)
|
||||
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
|
||||
|
||||
let string = "\(configuration ?? "nil"):TestEntity1:\(idIndex)"
|
||||
object.testString = string
|
||||
object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue)
|
||||
for idIndex in 1 ... 5 {
|
||||
|
||||
let object = transaction.create(Into<TestEntity1>(configuration))
|
||||
object.testEntityID = NSNumber(value: (configurationOrdinal * 100) + idIndex)
|
||||
|
||||
object.testNumber = NSNumber(value: idIndex)
|
||||
object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
|
||||
object.testBoolean = NSNumber(value: (idIndex % 2) == 1)
|
||||
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
|
||||
|
||||
let string = "\(configuration ?? "nil"):TestEntity1:\(idIndex)"
|
||||
object.testString = string
|
||||
object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
if configuration == nil || configuration == "Config2" {
|
||||
|
||||
for idIndex in 1 ... 5 {
|
||||
if configuration == nil || configuration == "Config2" {
|
||||
|
||||
let object = transaction.create(Into<TestEntity2>(configuration))
|
||||
object.testEntityID = NSNumber(value: (configurationOrdinal * 200) + idIndex)
|
||||
|
||||
object.testNumber = NSNumber(value: idIndex)
|
||||
object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
|
||||
object.testBoolean = NSNumber(value: (idIndex % 2) == 1)
|
||||
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
|
||||
|
||||
let string = "\(configuration ?? "nil"):TestEntity2:\(idIndex)"
|
||||
object.testString = string
|
||||
object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue)
|
||||
for idIndex in 1 ... 5 {
|
||||
|
||||
let object = transaction.create(Into<TestEntity2>(configuration))
|
||||
object.testEntityID = NSNumber(value: (configurationOrdinal * 200) + idIndex)
|
||||
|
||||
object.testNumber = NSNumber(value: idIndex)
|
||||
object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
|
||||
object.testBoolean = NSNumber(value: (idIndex % 2) == 1)
|
||||
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
|
||||
|
||||
let string = "\(configuration ?? "nil"):TestEntity2:\(idIndex)"
|
||||
object.testString = string
|
||||
object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = transaction.commitAndWait()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,15 +212,27 @@
|
||||
CSUnsafeDataTransaction *transaction = [CSCoreStore beginUnsafe];
|
||||
XCTAssertNotNil(transaction);
|
||||
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
|
||||
NSError *error;
|
||||
BOOL result = [transaction commitAndWaitWithError:&error];
|
||||
XCTAssertTrue(result);
|
||||
XCTAssertNil(error);
|
||||
}
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
|
||||
[CSCoreStore beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
|
||||
|
||||
XCTAssertNotNil(transaction);
|
||||
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
NSError *error;
|
||||
BOOL result = [CSCoreStore
|
||||
beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
|
||||
|
||||
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"];
|
||||
@@ -228,7 +240,15 @@
|
||||
|
||||
XCTAssertNotNil(transaction);
|
||||
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
|
||||
[expectation fulfill];
|
||||
[transaction
|
||||
commitWithSuccess:^{
|
||||
|
||||
[expectation fulfill];
|
||||
}
|
||||
failure:^(CSError *error){
|
||||
|
||||
XCTFail();
|
||||
}];
|
||||
}];
|
||||
}
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
|
||||
@@ -27,10 +27,9 @@
|
||||
import CoreStore
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ConvenienceTests
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
class ConvenienceTests: BaseTestCase {
|
||||
|
||||
@objc
|
||||
@@ -90,5 +89,3 @@ class ConvenienceTests: BaseTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
206
CoreStoreTests/DynamicModelTests.swift
Normal file
206
CoreStoreTests/DynamicModelTests.swift
Normal file
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// DynamicModelTests.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
|
||||
class Animal: CoreStoreObject {
|
||||
|
||||
let species = Value.Required<String>("species", default: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
|
||||
class Dog: Animal {
|
||||
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let age = Value.Required<Int>("age", default: 1)
|
||||
let friends = Relationship.ToManyOrdered<Dog>("friends")
|
||||
let friendedBy = Relationship.ToManyUnordered<Dog>("friendedBy", inverse: { $0.friends })
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let title = Value.Required<String>("title", default: "Mr.")
|
||||
let name = Value.Required<String>(
|
||||
"name",
|
||||
customGetter: { (`self`, getValue) in
|
||||
|
||||
return "\(self.title.value) \(getValue())"
|
||||
}
|
||||
)
|
||||
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
|
||||
}
|
||||
|
||||
|
||||
// MARK: - DynamicModelTests
|
||||
|
||||
class DynamicModelTests: BaseTestDataTestCase {
|
||||
|
||||
func testDynamicModels_CanBeDeclaredCorrectly() {
|
||||
|
||||
let dataStack = DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Dog>("Dog"),
|
||||
Entity<Person>("Person")
|
||||
],
|
||||
versionLock: [
|
||||
"Animal": [0x1b59d511019695cf, 0xdeb97e86c5eff179, 0x1cfd80745646cb3, 0x4ff99416175b5b9a],
|
||||
"Dog": [0xe3f0afeb109b283a, 0x29998d292938eb61, 0x6aab788333cfc2a3, 0x492ff1d295910ea7],
|
||||
"Person": [0x66d8bbfd8b21561f, 0xcecec69ecae3570f, 0xc4b73d71256214ef, 0x89b99bfe3e013e8b]
|
||||
]
|
||||
)
|
||||
)
|
||||
self.prepareStack(dataStack, configurations: [nil]) { (stack) in
|
||||
|
||||
let k1 = Animal.keyPath({ $0.species })
|
||||
XCTAssertEqual(k1, "species")
|
||||
|
||||
let k2 = Dog.keyPath({ $0.species })
|
||||
XCTAssertEqual(k2, "species")
|
||||
|
||||
let k3 = Dog.keyPath({ $0.nickname })
|
||||
XCTAssertEqual(k3, "nickname")
|
||||
|
||||
let updateDone = self.expectation(description: "update-done")
|
||||
let fetchDone = self.expectation(description: "fetch-done")
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let animal = transaction.create(Into<Animal>())
|
||||
XCTAssertEqual(animal.species.value, "Swift")
|
||||
XCTAssertTrue(type(of: animal.species.value) == String.self)
|
||||
|
||||
animal.species .= "Sparrow"
|
||||
XCTAssertEqual(animal.species.value, "Sparrow")
|
||||
|
||||
animal.color .= .yellow
|
||||
XCTAssertEqual(animal.color.value, UIColor.yellow)
|
||||
|
||||
let dog = transaction.create(Into<Dog>())
|
||||
XCTAssertEqual(dog.species.value, "Swift")
|
||||
XCTAssertEqual(dog.nickname.value, nil)
|
||||
XCTAssertEqual(dog.age.value, 1)
|
||||
|
||||
dog.species .= "Dog"
|
||||
XCTAssertEqual(dog.species.value, "Dog")
|
||||
|
||||
dog.nickname .= "Spot"
|
||||
XCTAssertEqual(dog.nickname.value, "Spot")
|
||||
|
||||
let person = transaction.create(Into<Person>())
|
||||
XCTAssertTrue(person.pets.value.isEmpty)
|
||||
|
||||
person.name .= "John"
|
||||
XCTAssertEqual(person.name.value, "Mr. John") // Custom getter
|
||||
|
||||
person.title .= "Sir"
|
||||
XCTAssertEqual(person.name.value, "Sir John")
|
||||
|
||||
person.pets.value.insert(dog)
|
||||
XCTAssertEqual(person.pets.count, 1)
|
||||
XCTAssertEqual(person.pets.value.first, dog)
|
||||
XCTAssertEqual(person.pets.value.first?.master.value, person)
|
||||
XCTAssertEqual(dog.master.value, person)
|
||||
XCTAssertEqual(dog.master.value?.pets.value.first, dog)
|
||||
},
|
||||
success: {
|
||||
|
||||
updateDone.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let p1 = Animal.where({ $0.species == "Sparrow" })
|
||||
XCTAssertEqual(p1.predicate, NSPredicate(format: "%K == %@", "species", "Sparrow"))
|
||||
|
||||
let bird = transaction.fetchOne(From<Animal>(), p1)
|
||||
XCTAssertNotNil(bird)
|
||||
XCTAssertEqual(bird!.species.value, "Sparrow")
|
||||
|
||||
let p2 = Dog.where({ $0.nickname == "Spot" })
|
||||
XCTAssertEqual(p2.predicate, NSPredicate(format: "%K == %@", "nickname", "Spot"))
|
||||
|
||||
let dog = transaction.fetchOne(From<Dog>(), p2)
|
||||
XCTAssertNotNil(dog)
|
||||
XCTAssertEqual(dog!.nickname.value, "Spot")
|
||||
XCTAssertEqual(dog!.species.value, "Dog")
|
||||
|
||||
let person = transaction.fetchOne(From<Person>())
|
||||
XCTAssertNotNil(person)
|
||||
XCTAssertEqual(person!.pets.value.first, dog)
|
||||
|
||||
let p3 = Dog.where({ $0.age == 10 })
|
||||
XCTAssertEqual(p3.predicate, NSPredicate(format: "%K == %d", "age", 10))
|
||||
},
|
||||
success: {
|
||||
|
||||
fetchDone.fulfill()
|
||||
withExtendedLifetime(stack, {})
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
func prepareStack(_ dataStack: DataStack, configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> Void) {
|
||||
|
||||
do {
|
||||
|
||||
try configurations.forEach { (configuration) in
|
||||
|
||||
try dataStack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileURL: SQLiteStore.defaultRootDirectory
|
||||
.appendingPathComponent(UUID().uuidString)
|
||||
.appendingPathComponent("\(type(of: self))_\((configuration ?? "-null-")).sqlite"),
|
||||
configuration: configuration,
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
catch let error as NSError {
|
||||
|
||||
XCTFail(error.coreStoreDumpString)
|
||||
}
|
||||
closure(dataStack)
|
||||
}
|
||||
}
|
||||
@@ -85,16 +85,19 @@ final class ErrorTests: XCTestCase {
|
||||
|
||||
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
|
||||
|
||||
let model = NSManagedObjectModel.fromBundle(Bundle(for: type(of: self)), modelName: "Model")
|
||||
let schemaHistory = SchemaHistory(
|
||||
modelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
let version = "1.0.0"
|
||||
|
||||
let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version)
|
||||
let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: schemaHistory.rawModel, targetModelVersion: version)
|
||||
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
|
||||
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
|
||||
|
||||
let userInfo: NSDictionary = [
|
||||
"localStoreURL": dummyURL,
|
||||
"targetModel": model,
|
||||
"targetModel": schemaHistory.rawModel,
|
||||
"targetModelVersion": version
|
||||
]
|
||||
let objcError = error.bridgeToObjectiveC
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@ final class FromTests: BaseTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let from = From()
|
||||
let from = From<NSManagedObject>()
|
||||
XCTAssert(from.entityClass === NSManagedObject.self)
|
||||
XCTAssertNil(from.configurations)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@ final class IntoTests: XCTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatIntoClauseConstants_AreCorrect() {
|
||||
|
||||
XCTAssertEqual(Into<NSManagedObject>.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
|
||||
XCTAssertEqual(DataStack.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -44,7 +44,7 @@ final class IntoTests: XCTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let into = Into()
|
||||
let into = Into<NSManagedObject>()
|
||||
XCTAssert(into.entityClass === NSManagedObject.self)
|
||||
XCTAssertNil(into.configuration)
|
||||
XCTAssertTrue(into.inferStoreIfPossible)
|
||||
@@ -58,14 +58,7 @@ final class IntoTests: XCTestCase {
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
XCTAssert(into.entityClass === TestEntity1.self)
|
||||
XCTAssertNil(into.configuration)
|
||||
XCTAssertTrue(into.inferStoreIfPossible)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let into = Into(TestEntity1.self)
|
||||
XCTAssert(into.entityClass === TestEntity1.self)
|
||||
XCTAssertNil(into.configuration)
|
||||
XCTAssertTrue(into.inferStoreIfPossible)
|
||||
@@ -84,13 +77,6 @@ final class IntoTests: XCTestCase {
|
||||
XCTAssertEqual(into.configuration, "Config1")
|
||||
XCTAssertFalse(into.inferStoreIfPossible)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
||||
XCTAssert(into.entityClass === TestEntity1.self)
|
||||
XCTAssertEqual(into.configuration, "Config1")
|
||||
XCTAssertFalse(into.inferStoreIfPossible)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -98,43 +84,30 @@ final class IntoTests: XCTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let into = Into()
|
||||
XCTAssertEqual(into, Into())
|
||||
let into = Into<NSManagedObject>()
|
||||
XCTAssertEqual(into, Into<NSManagedObject>())
|
||||
XCTAssertEqual(into, Into(NSManagedObject.self as AnyClass))
|
||||
XCTAssertFalse(into == Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(NSManagedObject.self))
|
||||
XCTAssertNotEqual(into, Into<NSManagedObject>(TestEntity1.self))
|
||||
XCTAssertNotEqual(into, Into<NSManagedObject>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
XCTAssertEqual(into, Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
|
||||
XCTAssertFalse(into == Into<TestEntity2>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
XCTAssertEqual(into, Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
|
||||
XCTAssertFalse(into == Into<TestEntity2>())
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let into = Into(TestEntity1.self)
|
||||
XCTAssert(into == Into<TestEntity1>())
|
||||
XCTAssertEqual(into, Into(TestEntity1.self))
|
||||
XCTAssertFalse(into == Into<TestEntity2>())
|
||||
XCTAssertFalse(into == Into<TestEntity1>("Config1"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>("Config1")
|
||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass, "Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||
}
|
||||
do {
|
||||
@@ -142,16 +115,14 @@ final class IntoTests: XCTestCase {
|
||||
let into = Into(TestEntity1.self, "Config1")
|
||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
||||
XCTAssert(into == Into<TestEntity1>("Config1"))
|
||||
let into = Into(TestEntity1.self, "Config1")
|
||||
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
|
||||
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
|
||||
XCTAssertFalse(into == Into<TestEntity1>("Config2"))
|
||||
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,45 +131,9 @@ final class IntoTests: XCTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let into = Into()
|
||||
let into = Into<NSManagedObject>()
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>()
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass)
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertEqual(into, objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into<TestEntity1>("Config1")
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self, "Config1")
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
do {
|
||||
|
||||
let into = Into(TestEntity1.self as AnyClass, "Config1")
|
||||
let objcInto = into.bridgeToObjectiveC
|
||||
XCTAssertTrue(into == objcInto.bridgeToSwift)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,9 @@ import XCTest
|
||||
import CoreStore
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ListObserverTests
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
class ListObserverTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
@@ -103,8 +102,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
)
|
||||
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssertEqual(indexPath?.row, 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
@@ -134,29 +133,29 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
}
|
||||
)
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.beginAsynchronous { (transaction) 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")!
|
||||
|
||||
transaction.commit { (result) in
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
switch result {
|
||||
|
||||
case .success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -221,8 +220,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
switch object?.testEntityID {
|
||||
|
||||
case NSNumber(value: 101)?:
|
||||
XCTAssertEqual(indexPath?.section, 1)
|
||||
XCTAssertEqual(indexPath?.row, 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
|
||||
@@ -232,8 +231,8 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
|
||||
|
||||
case NSNumber(value: 102)?:
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssertEqual(indexPath?.row, 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
|
||||
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
|
||||
@@ -268,49 +267,49 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
}
|
||||
)
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
if let object = transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
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 = transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where(#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()
|
||||
}
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
if let object = transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
|
||||
|
||||
case .success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
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 {
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
if let object = transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where(#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()
|
||||
}
|
||||
}
|
||||
@@ -361,12 +360,12 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
)
|
||||
|
||||
let fromIndexPath = userInfo?["fromIndexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(fromIndexPath?.section, 0)
|
||||
XCTAssertEqual(fromIndexPath?.row, 0)
|
||||
XCTAssertEqual(fromIndexPath?.index(atPosition: 0), 0)
|
||||
XCTAssertEqual(fromIndexPath?.index(atPosition: 1), 0)
|
||||
|
||||
let toIndexPath = userInfo?["toIndexPath"] as? NSIndexPath
|
||||
XCTAssertEqual(toIndexPath?.section, 1)
|
||||
XCTAssertEqual(toIndexPath?.row, 1)
|
||||
XCTAssertEqual(toIndexPath?.index(atPosition: 0), 1)
|
||||
XCTAssertEqual(toIndexPath?.index(atPosition: 1), 1)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
|
||||
@@ -394,31 +393,31 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
}
|
||||
)
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
if let object = transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
object.testBoolean = NSNumber(value: true)
|
||||
}
|
||||
else {
|
||||
if let object = transaction.fetchOne(
|
||||
From<TestEntity1>(),
|
||||
Where(#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()
|
||||
}
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
}
|
||||
@@ -473,7 +472,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
let indexPath = userInfo?["indexPath"] as? NSIndexPath
|
||||
|
||||
XCTAssertEqual(indexPath?.section, 0)
|
||||
XCTAssert(indexPath?.row == 0 || indexPath?.row == 1)
|
||||
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
|
||||
|
||||
let object = userInfo?["object"] as? TestEntity1
|
||||
XCTAssertEqual(object?.isDeleted, true)
|
||||
@@ -529,25 +528,25 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
}
|
||||
)
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
transaction.deleteAll(
|
||||
From<TestEntity1>(),
|
||||
Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
|
||||
)
|
||||
transaction.commit { (result) in
|
||||
stack.perform(
|
||||
asynchronous: { (transaction) -> Bool in
|
||||
|
||||
switch result {
|
||||
|
||||
case .success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
transaction.deleteAll(
|
||||
From<TestEntity1>(),
|
||||
Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
|
||||
)
|
||||
return transaction.hasChanges
|
||||
},
|
||||
success: { (hasChanges) in
|
||||
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
}
|
||||
@@ -556,6 +555,7 @@ class ListObserverTests: BaseTestDataTestCase {
|
||||
|
||||
// MARK: TestListObserver
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
class TestListObserver: ListSectionObserver {
|
||||
|
||||
// MARK: ListObserver
|
||||
@@ -678,5 +678,3 @@ class TestListObserver: ListSectionObserver {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,8 +37,8 @@ final class MigrationChainTests: XCTestCase {
|
||||
dynamic func test_ThatNilMigrationChains_HaveNoVersions() {
|
||||
|
||||
let chain: MigrationChain = nil
|
||||
XCTAssertTrue(chain.valid)
|
||||
XCTAssertTrue(chain.empty)
|
||||
XCTAssertTrue(chain.isValid)
|
||||
XCTAssertTrue(chain.isEmpty)
|
||||
|
||||
XCTAssertFalse(chain.contains("version1"))
|
||||
XCTAssertNil(chain.nextVersionFrom("version1"))
|
||||
@@ -48,8 +48,8 @@ final class MigrationChainTests: XCTestCase {
|
||||
dynamic func test_ThatStringMigrationChains_HaveOneVersion() {
|
||||
|
||||
let chain: MigrationChain = "version1"
|
||||
XCTAssertTrue(chain.valid)
|
||||
XCTAssertTrue(chain.empty)
|
||||
XCTAssertTrue(chain.isValid)
|
||||
XCTAssertTrue(chain.isEmpty)
|
||||
|
||||
XCTAssertTrue(chain.contains("version1"))
|
||||
XCTAssertFalse(chain.contains("version2"))
|
||||
@@ -62,8 +62,8 @@ final class MigrationChainTests: XCTestCase {
|
||||
dynamic func test_ThatArrayMigrationChains_HaveLinearVersions() {
|
||||
|
||||
let chain: MigrationChain = ["version1", "version2", "version3", "version4"]
|
||||
XCTAssertTrue(chain.valid)
|
||||
XCTAssertFalse(chain.empty)
|
||||
XCTAssertTrue(chain.isValid)
|
||||
XCTAssertFalse(chain.isEmpty)
|
||||
|
||||
XCTAssertTrue(chain.contains("version1"))
|
||||
XCTAssertTrue(chain.contains("version2"))
|
||||
@@ -86,8 +86,8 @@ final class MigrationChainTests: XCTestCase {
|
||||
"version2": "version3",
|
||||
"version3": "version4"
|
||||
]
|
||||
XCTAssertTrue(chain.valid)
|
||||
XCTAssertFalse(chain.empty)
|
||||
XCTAssertTrue(chain.isValid)
|
||||
XCTAssertFalse(chain.isEmpty)
|
||||
|
||||
XCTAssertTrue(chain.contains("version1"))
|
||||
XCTAssertTrue(chain.contains("version2"))
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10174" systemVersion="15F34" minimumToolsVersion="Xcode 4.3">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11759" systemVersion="16C67" minimumToolsVersion="Xcode 4.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
|
||||
<entity name="TestEntity1AAA" representedClassName="CoreStoreTests.TestEntity1" syncable="YES">
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
|
||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="TestEntity2" representedClassName="CoreStoreTests.TestEntity2" syncable="YES">
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
|
||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
||||
</entity>
|
||||
<configuration name="Config1">
|
||||
|
||||
@@ -29,10 +29,9 @@ import XCTest
|
||||
import CoreStore
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ObjectObserverTests
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
class ObjectObserverTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
@@ -105,29 +104,29 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
||||
}
|
||||
)
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
guard let object = transaction.edit(object) else {
|
||||
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()
|
||||
return
|
||||
}
|
||||
object.testNumber = NSNumber(value: 10)
|
||||
object.testString = "nil:TestEntity1:10"
|
||||
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
saveExpectation.fulfill()
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
}
|
||||
@@ -173,29 +172,29 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
||||
}
|
||||
)
|
||||
let saveExpectation = self.expectation(description: "save")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
guard let object = transaction.edit(object) else {
|
||||
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)
|
||||
XCTAssertTrue(monitor.isObjectDeleted)
|
||||
saveExpectation.fulfill()
|
||||
},
|
||||
failure: { _ in
|
||||
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
transaction.delete(object)
|
||||
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
XCTAssertTrue(monitor.isObjectDeleted)
|
||||
saveExpectation.fulfill()
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
}
|
||||
@@ -204,6 +203,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
|
||||
|
||||
// MARK: TestObjectObserver
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
class TestObjectObserver: ObjectObserver {
|
||||
|
||||
typealias ObjectEntityType = TestEntity1
|
||||
@@ -242,5 +242,3 @@ class TestObjectObserver: ObjectObserver {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAttributeValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -220,7 +220,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAverageValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -399,7 +399,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryCountValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -576,7 +576,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryMaximumValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -760,7 +760,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryMinimumValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -944,7 +944,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQuerySumValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1122,7 +1122,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryObjectIDValue() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1290,7 +1290,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAttributes() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
@@ -1344,7 +1344,7 @@ class QueryTests: BaseTestDataTestCase {
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanQueryAggregates() {
|
||||
|
||||
let configurations: [String?] = [nil]
|
||||
let configurations: [ModelConfiguration] = [nil]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
|
||||
@@ -29,10 +29,9 @@ import XCTest
|
||||
import CoreStore
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
//MARK: - SectionByTests
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
final class SectionByTests: XCTestCase {
|
||||
|
||||
@objc
|
||||
@@ -53,5 +52,3 @@ final class SectionByTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,10 +36,13 @@ class SetupTests: BaseTestDataTestCase {
|
||||
|
||||
do {
|
||||
|
||||
let model = NSManagedObjectModel.mergedModel(from: [Bundle(for: type(of: self))])!
|
||||
|
||||
let stack = DataStack(model: model, migrationChain: nil)
|
||||
XCTAssertEqual(stack.coordinator.managedObjectModel, model)
|
||||
let schemaHistory = SchemaHistory(
|
||||
modelName: "Model",
|
||||
bundle: Bundle(for: type(of: self)),
|
||||
migrationChain: nil
|
||||
)
|
||||
let stack = DataStack(schemaHistory: schemaHistory)
|
||||
XCTAssertEqual(stack.coordinator.managedObjectModel, schemaHistory.rawModel)
|
||||
XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator)
|
||||
XCTAssertNil(stack.rootSavingContext.parent)
|
||||
XCTAssertFalse(stack.rootSavingContext.isDataStackContext)
|
||||
@@ -47,18 +50,18 @@ class SetupTests: BaseTestDataTestCase {
|
||||
XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext)
|
||||
XCTAssertTrue(stack.mainContext.isDataStackContext)
|
||||
XCTAssertFalse(stack.mainContext.isTransactionContext)
|
||||
XCTAssertEqual(stack.model, model)
|
||||
XCTAssertTrue(stack.migrationChain.valid)
|
||||
XCTAssertTrue(stack.migrationChain.empty)
|
||||
XCTAssertTrue(stack.migrationChain.rootVersions.isEmpty)
|
||||
XCTAssertTrue(stack.migrationChain.leafVersions.isEmpty)
|
||||
XCTAssertEqual(stack.schemaHistory.rawModel, schemaHistory.rawModel)
|
||||
XCTAssertTrue(stack.schemaHistory.migrationChain.isValid)
|
||||
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 {
|
||||
|
||||
let migrationChain: MigrationChain = ["version1", "version2", "version3"]
|
||||
let migrationChain: MigrationChain = ["version1", "version2", "version3", "Model"]
|
||||
|
||||
let stack = self.expectLogger([.logWarning]) {
|
||||
|
||||
@@ -69,7 +72,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
)
|
||||
}
|
||||
XCTAssertEqual(stack.modelVersion, "Model")
|
||||
XCTAssertEqual(stack.migrationChain, migrationChain)
|
||||
XCTAssertEqual(stack.schemaHistory.migrationChain, migrationChain)
|
||||
|
||||
CoreStore.defaultStack = stack
|
||||
XCTAssertEqual(CoreStore.defaultStack, stack)
|
||||
@@ -210,7 +213,6 @@ class SetupTests: BaseTestDataTestCase {
|
||||
self.prepareTestDataForStack(stack)
|
||||
}
|
||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||
|
||||
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||
@@ -226,7 +228,10 @@ class SetupTests: BaseTestDataTestCase {
|
||||
modelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata])
|
||||
try sqliteStore.eraseStorageAndWait(
|
||||
metadata: metadata,
|
||||
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
|
||||
)
|
||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||
@@ -258,7 +263,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
)
|
||||
do {
|
||||
|
||||
let sqliteStore = LegacySQLiteStore()
|
||||
let sqliteStore = SQLiteStore.legacy()
|
||||
do {
|
||||
|
||||
try stack.addStorageAndWait(sqliteStore)
|
||||
@@ -273,7 +278,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
}
|
||||
do {
|
||||
|
||||
let sqliteStore = LegacySQLiteStore(
|
||||
let sqliteStore = SQLiteStore.legacy(
|
||||
fileName: "ConfigStore1.sqlite",
|
||||
configuration: "Config1",
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
@@ -292,7 +297,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
}
|
||||
do {
|
||||
|
||||
let sqliteStore = LegacySQLiteStore(
|
||||
let sqliteStore = SQLiteStore.legacy(
|
||||
fileName: "ConfigStore2.sqlite",
|
||||
configuration: "Config2",
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
@@ -315,7 +320,7 @@ class SetupTests: BaseTestDataTestCase {
|
||||
dynamic func test_ThatLegacySQLiteStores_DeleteFilesCorrectly() {
|
||||
|
||||
let fileManager = FileManager.default
|
||||
let sqliteStore = LegacySQLiteStore()
|
||||
let sqliteStore = SQLiteStore.legacy()
|
||||
func createStore() throws -> [String: Any] {
|
||||
|
||||
do {
|
||||
@@ -328,7 +333,6 @@ class SetupTests: BaseTestDataTestCase {
|
||||
self.prepareTestDataForStack(stack)
|
||||
}
|
||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||
|
||||
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||
@@ -344,7 +348,10 @@ class SetupTests: BaseTestDataTestCase {
|
||||
modelName: "Model",
|
||||
bundle: Bundle(for: type(of: self))
|
||||
)
|
||||
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata])
|
||||
try sqliteStore.eraseStorageAndWait(
|
||||
metadata: metadata,
|
||||
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
|
||||
)
|
||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
|
||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
|
||||
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
|
||||
|
||||
@@ -86,7 +86,7 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||
|
||||
XCTAssertEqual(store.fileURL, SQLiteStore.defaultFileURL)
|
||||
XCTAssertEqual(store.mappingModelBundles, Bundle.allBundles)
|
||||
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
|
||||
XCTAssertEqual(store.localStorageOptions, .none)
|
||||
}
|
||||
|
||||
@@ -96,12 +96,15 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
|
||||
.appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
|
||||
.appendingPathExtension("db")
|
||||
let bundles = [Bundle(for: type(of: self))]
|
||||
let mappingProvider = XcodeSchemaMappingProvider(
|
||||
from: "V1", to: "V2",
|
||||
mappingModelBundle: Bundle(for: type(of: self))
|
||||
)
|
||||
|
||||
let store = SQLiteStore(
|
||||
fileURL: fileURL,
|
||||
configuration: "config1",
|
||||
mappingModelBundles: bundles,
|
||||
migrationMappingProviders: [mappingProvider],
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||
@@ -109,7 +112,7 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||
|
||||
XCTAssertEqual(store.fileURL, fileURL)
|
||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
||||
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
|
||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||
}
|
||||
|
||||
@@ -117,12 +120,14 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() {
|
||||
|
||||
let fileName = UUID().uuidString + ".db"
|
||||
let bundles = [Bundle(for: type(of: self))]
|
||||
|
||||
let mappingProvider = XcodeSchemaMappingProvider(
|
||||
from: "V1", to: "V2",
|
||||
mappingModelBundle: Bundle(for: type(of: self))
|
||||
)
|
||||
let store = SQLiteStore(
|
||||
fileName: fileName,
|
||||
configuration: "config1",
|
||||
mappingModelBundles: bundles,
|
||||
migrationMappingProviders: [mappingProvider],
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||
@@ -131,7 +136,7 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.defaultRootDirectory)
|
||||
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
|
||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
||||
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
|
||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||
}
|
||||
|
||||
@@ -152,65 +157,44 @@ final class StorageInterfaceTests: XCTestCase {
|
||||
.appendingPathComponent(DataStack.applicationName, isDirectory: false)
|
||||
.appendingPathExtension("sqlite")
|
||||
|
||||
XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory)
|
||||
XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL)
|
||||
XCTAssertEqual(SQLiteStore.legacyDefaultRootDirectory, legacyDefaultRootDirectory)
|
||||
XCTAssertEqual(SQLiteStore.legacyDefaultFileURL, legacyDefaultFileURL)
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() {
|
||||
|
||||
let store = LegacySQLiteStore()
|
||||
let store = SQLiteStore.legacy()
|
||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||
XCTAssertNil(store.configuration)
|
||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||
|
||||
XCTAssertEqual(store.fileURL, LegacySQLiteStore.defaultFileURL)
|
||||
XCTAssertEqual(store.mappingModelBundles, Bundle.allBundles)
|
||||
XCTAssertEqual(store.fileURL, SQLiteStore.legacyDefaultFileURL)
|
||||
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
|
||||
XCTAssertEqual(store.localStorageOptions, .none)
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() {
|
||||
|
||||
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
|
||||
.appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
|
||||
.appendingPathExtension("db")
|
||||
let bundles = [Bundle(for: type(of: self))]
|
||||
|
||||
let store = LegacySQLiteStore(
|
||||
fileURL: fileURL,
|
||||
configuration: "config1",
|
||||
mappingModelBundles: bundles,
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||
XCTAssertEqual(store.configuration, "config1")
|
||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||
|
||||
XCTAssertEqual(store.fileURL, fileURL)
|
||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() {
|
||||
|
||||
let fileName = UUID().uuidString + ".db"
|
||||
let bundles = [Bundle(for: type(of: self))]
|
||||
|
||||
let store = LegacySQLiteStore(
|
||||
let mappingProvider = XcodeSchemaMappingProvider(
|
||||
from: "V1", to: "V2",
|
||||
mappingModelBundle: Bundle(for: type(of: self))
|
||||
)
|
||||
let store = SQLiteStore.legacy(
|
||||
fileName: fileName,
|
||||
configuration: "config1",
|
||||
mappingModelBundles: bundles,
|
||||
migrationMappingProviders: [mappingProvider],
|
||||
localStorageOptions: .recreateStoreOnModelMismatch
|
||||
)
|
||||
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
|
||||
XCTAssertEqual(store.configuration, "config1")
|
||||
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
|
||||
|
||||
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), LegacySQLiteStore.defaultRootDirectory)
|
||||
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.legacyDefaultRootDirectory)
|
||||
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
|
||||
XCTAssertEqual(store.mappingModelBundles, bundles)
|
||||
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
|
||||
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,25 @@ import XCTest
|
||||
import CoreStore
|
||||
|
||||
|
||||
// MARK: - XCTAssertAllEqual
|
||||
|
||||
private func XCTAssertAllEqual(_ whereClauses: Where...) {
|
||||
|
||||
XCTAssertAllEqual(whereClauses)
|
||||
}
|
||||
|
||||
private func XCTAssertAllEqual(_ whereClauses: [Where]) {
|
||||
|
||||
for i in whereClauses.indices {
|
||||
|
||||
for j in whereClauses.indices where j != i {
|
||||
|
||||
XCTAssertEqual(whereClauses[i], whereClauses[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//MARK: - WhereTests
|
||||
|
||||
final class WhereTests: XCTestCase {
|
||||
@@ -93,202 +112,114 @@ final class WhereTests: XCTestCase {
|
||||
do {
|
||||
|
||||
let value: Int = 100
|
||||
let whereClause1 = Where("%K == %d", "key", value)
|
||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %d", "key", NSNumber(value: value))
|
||||
let whereClause4 = Where("%K == %@", "key", value)
|
||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause6 = Where("%K == %@", "key", NSNumber(value: value))
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K == %d", "key", value),
|
||||
Where("%K == %d", "key", value as AnyObject),
|
||||
Where("%K == %d", "key", NSNumber(value: value)),
|
||||
Where("%K == %@", "key", value),
|
||||
Where("%K == %@", "key", value as AnyObject),
|
||||
Where("%K == %@", "key", NSNumber(value: value)),
|
||||
Where("key", isEqualTo: value),
|
||||
Where("key", isEqualTo: NSNumber(value: value))
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value = NSNumber(value: 100)
|
||||
let whereClause1 = Where("%K == %d", "key", value)
|
||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %d", "key", value.intValue)
|
||||
let whereClause4 = Where("%K == %@", "key", value)
|
||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause6 = Where("%K == %@", "key", value.intValue)
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K == %d", "key", value),
|
||||
Where("%K == %d", "key", value as AnyObject),
|
||||
Where("%K == %d", "key", value.intValue),
|
||||
Where("%K == %@", "key", value),
|
||||
Where("%K == %@", "key", value as AnyObject),
|
||||
Where("%K == %@", "key", value.intValue),
|
||||
Where("key", isEqualTo: value),
|
||||
Where("key", isEqualTo: value.intValue)
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value: Int64 = Int64.max
|
||||
let whereClause1 = Where("%K == %d", "key", value)
|
||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %d", "key", NSNumber(value: value))
|
||||
let whereClause4 = Where("%K == %@", "key", value)
|
||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause6 = Where("%K == %@", "key", NSNumber(value: value))
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K == %d", "key", value),
|
||||
Where("%K == %d", "key", value as AnyObject),
|
||||
Where("%K == %d", "key", NSNumber(value: value)),
|
||||
Where("%K == %@", "key", value),
|
||||
Where("%K == %@", "key", value as AnyObject),
|
||||
Where("%K == %@", "key", NSNumber(value: value)),
|
||||
Where("key", isEqualTo: value),
|
||||
Where("key", isEqualTo: NSNumber(value: value))
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value = NSNumber(value: Int64.max)
|
||||
let whereClause1 = Where("%K == %d", "key", value)
|
||||
let whereClause2 = Where("%K == %d", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %d", "key", value.int64Value)
|
||||
let whereClause4 = Where("%K == %@", "key", value)
|
||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause6 = Where("%K == %@", "key", value.int64Value)
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K == %d", "key", value),
|
||||
Where("%K == %d", "key", value as AnyObject),
|
||||
Where("%K == %d", "key", value.int64Value),
|
||||
Where("%K == %@", "key", value),
|
||||
Where("%K == %@", "key", value as AnyObject),
|
||||
Where("%K == %@", "key", value.int64Value),
|
||||
Where("key", isEqualTo: value),
|
||||
Where("key", isEqualTo: value.int64Value)
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value: String = "value"
|
||||
let whereClause1 = Where("%K == %s", "key", value)
|
||||
let whereClause2 = Where("%K == %s", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %s", "key", NSString(string: value))
|
||||
let whereClause4 = Where("%K == %@", "key", value)
|
||||
let whereClause5 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause6 = Where("%K == %@", "key", NSString(string: value))
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K == %s", "key", value),
|
||||
Where("%K == %s", "key", value as AnyObject),
|
||||
Where("%K == %s", "key", NSString(string: value)),
|
||||
Where("%K == %@", "key", value),
|
||||
Where("%K == %@", "key", value as AnyObject),
|
||||
Where("%K == %@", "key", NSString(string: value)),
|
||||
Where("key", isEqualTo: value),
|
||||
Where("key", isEqualTo: value as NSString),
|
||||
Where("key", isEqualTo: NSString(string: value))
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value = NSString(string: "value")
|
||||
let whereClause1 = Where("%K == %s", "key", value)
|
||||
let whereClause2 = Where("%K == %s", "key", value as String)
|
||||
let whereClause3 = Where("%K == %s", "key", value as String as AnyObject)
|
||||
let whereClause4 = Where("%K == %@", "key", value)
|
||||
let whereClause5 = Where("%K == %@", "key", value as String)
|
||||
let whereClause6 = Where("%K == %@", "key", value as String as AnyObject)
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K == %s", "key", value),
|
||||
Where("%K == %s", "key", value as String),
|
||||
Where("%K == %s", "key", value as String as AnyObject),
|
||||
Where("%K == %@", "key", value),
|
||||
Where("%K == %@", "key", value as String),
|
||||
Where("%K == %@", "key", value as String as AnyObject),
|
||||
Where("key", isEqualTo: value),
|
||||
Where("key", isEqualTo: value as String),
|
||||
Where("key", isEqualTo: value as String as NSString)
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value: [Int] = [100, 200]
|
||||
let whereClause1 = Where("%K == %@", "key", value)
|
||||
let whereClause2 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %@", "key", value as [AnyObject])
|
||||
let whereClause4 = Where("%K == %@", "key", value as NSArray)
|
||||
let whereClause5 = Where("%K == %@", "key", NSArray(array: value))
|
||||
let whereClause6 = Where("%K == %@", "key", value as AnyObject as! NSArray)
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K IN %@", "key", value),
|
||||
Where("%K IN %@", "key", value as AnyObject),
|
||||
Where("%K IN %@", "key", value as [AnyObject]),
|
||||
Where("%K IN %@", "key", value as NSArray),
|
||||
Where("%K IN %@", "key", NSArray(array: value)),
|
||||
Where("%K IN %@", "key", value as AnyObject as! NSArray),
|
||||
Where("key", isMemberOf: value)
|
||||
)
|
||||
}
|
||||
do {
|
||||
|
||||
let value: [Int64] = [Int64.min, 100, Int64.max]
|
||||
let whereClause1 = Where("%K == %@", "key", value)
|
||||
let whereClause2 = Where("%K == %@", "key", value as AnyObject)
|
||||
let whereClause3 = Where("%K == %@", "key", value as [AnyObject])
|
||||
let whereClause4 = Where("%K == %@", "key", value as NSArray)
|
||||
let whereClause5 = Where("%K == %@", "key", NSArray(array: value))
|
||||
let whereClause6 = Where("%K == %@", "key", value as AnyObject as! NSArray)
|
||||
XCTAssertEqual(whereClause1, whereClause2)
|
||||
XCTAssertEqual(whereClause1, whereClause3)
|
||||
XCTAssertEqual(whereClause1, whereClause4)
|
||||
XCTAssertEqual(whereClause1, whereClause5)
|
||||
XCTAssertEqual(whereClause1, whereClause6)
|
||||
XCTAssertEqual(whereClause2, whereClause3)
|
||||
XCTAssertEqual(whereClause2, whereClause4)
|
||||
XCTAssertEqual(whereClause2, whereClause5)
|
||||
XCTAssertEqual(whereClause2, whereClause6)
|
||||
XCTAssertEqual(whereClause3, whereClause4)
|
||||
XCTAssertEqual(whereClause3, whereClause5)
|
||||
XCTAssertEqual(whereClause3, whereClause6)
|
||||
XCTAssertEqual(whereClause4, whereClause5)
|
||||
XCTAssertEqual(whereClause4, whereClause6)
|
||||
XCTAssertEqual(whereClause5, whereClause6)
|
||||
XCTAssertAllEqual(
|
||||
Where("%K IN %@", "key", value),
|
||||
Where("%K IN %@", "key", value as AnyObject),
|
||||
Where("%K IN %@", "key", value as [AnyObject]),
|
||||
Where("%K IN %@", "key", value as NSArray),
|
||||
Where("%K IN %@", "key", NSArray(array: value)),
|
||||
Where("%K IN %@", "key", value as AnyObject as! NSArray),
|
||||
Where("key", isMemberOf: value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -270,10 +270,6 @@ try CoreStore.addStorageAndWait(
|
||||
)
|
||||
)
|
||||
```
|
||||
`InMemoryStore`s also implement the `DefaultInitializableStore` sugar protocol which tells CoreStore that this store can initialize without any arguments (`init()`). This lets us provide just the type instead of an instance:
|
||||
```swift
|
||||
try CoreStore.addStorageAndWait(InMemoryStore.self)
|
||||
```
|
||||
|
||||
### Local Store
|
||||
The most common `StorageInterface` you will probably use is the `SQLiteStore`, which saves data in a local SQLite file.
|
||||
@@ -290,9 +286,9 @@ let migrationProgress = CoreStore.addStorage(
|
||||
```
|
||||
Refer to the *SQLiteStore.swift* source documentation for detailed explanations for each of the default values.
|
||||
|
||||
CoreStore can decide the default values for these properties, so `SQLiteStore`s also implement the `DefaultInitializableStore` sugar protocol which lets us write:
|
||||
CoreStore can decide the default values for these properties, so `SQLiteStore`s can be initialized with default arguments:
|
||||
```swift
|
||||
try CoreStore.addStorageAndWait(SQLiteStore.self)
|
||||
try CoreStore.addStorageAndWait(SQLiteStore())
|
||||
```
|
||||
or
|
||||
```swift
|
||||
@@ -519,7 +515,7 @@ are created from `beginSynchronous(...)`. While the syntax is similar to its asy
|
||||
```swift
|
||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
// make changes
|
||||
transaction.commit()
|
||||
_ = transaction.commit()
|
||||
}
|
||||
```
|
||||
`transaction` above is a `SynchronousDataTransaction` instance.
|
||||
@@ -815,7 +811,7 @@ public protocol ImportableUniqueObject: ImportableObject {
|
||||
static var uniqueIDKeyPath: String { get }
|
||||
var uniqueIDValue: UniqueIDType { get set }
|
||||
|
||||
static func shouldInsert(from source: ImportSource, inn transaction: BaseDataTransaction) -> Bool
|
||||
static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool
|
||||
static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool
|
||||
static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> UniqueIDType?
|
||||
func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws
|
||||
|
||||
@@ -34,68 +34,61 @@ import CoreData
|
||||
*/
|
||||
public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
|
||||
/**
|
||||
Saves the transaction changes. This method should not be used after the `commit()` method was already called once.
|
||||
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
|
||||
*/
|
||||
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
|
||||
// MARK: - Result
|
||||
|
||||
public enum Result<T> {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||
)
|
||||
case success(userInfo: T)
|
||||
case failure(error: CoreStoreError)
|
||||
|
||||
self.isCommitted = true
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
|
||||
public var boolValue: Bool {
|
||||
|
||||
self.result = result
|
||||
completion(result)
|
||||
group.leave()
|
||||
switch self {
|
||||
|
||||
case .success: return true
|
||||
case .failure: return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(userInfo: T) {
|
||||
|
||||
self = .success(userInfo: userInfo)
|
||||
}
|
||||
|
||||
internal init(error: CoreStoreError) {
|
||||
|
||||
self = .failure(error: error)
|
||||
}
|
||||
group.wait()
|
||||
}
|
||||
|
||||
|
||||
// MARK: -
|
||||
|
||||
/**
|
||||
Begins a child transaction synchronously where NSManagedObject creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
Cancels a transaction by throwing `CoreStoreError.userCancelled`.
|
||||
```
|
||||
try transaction.cancel()
|
||||
```
|
||||
- Important: Never use `try?` or `try!` on a `cancel()` call. Always use `try`. Using `try?` will swallow the cancellation and the transaction will proceed to commit as normal. Using `try!` will crash the app as `cancel()` will *always* throw an error.
|
||||
*/
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
|
||||
public func cancel() throws -> Never {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to begin a child transaction from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return SynchronousDataTransaction(
|
||||
mainContext: self.context,
|
||||
queue: self.childTransactionQueue,
|
||||
closure: closure).performAndWait()
|
||||
throw CoreStoreError.userCancelled
|
||||
}
|
||||
|
||||
|
||||
// MARK: BaseDataTransaction
|
||||
|
||||
/**
|
||||
Creates a new `NSManagedObject` with the specified entity type.
|
||||
Creates a new `NSManagedObject` or `CoreStoreObject` with the specified entity type.
|
||||
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
|
||||
*/
|
||||
public override func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
||||
public override func create<T: DynamicObject>(_ into: Into<T>) -> T {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -111,7 +104,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter object: the `NSManagedObject` type to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
||||
*/
|
||||
public override func edit<T: NSManagedObject>(_ object: T?) -> T? {
|
||||
public override func edit<T: DynamicObject>(_ object: T?) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -128,7 +121,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
||||
*/
|
||||
public override func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
public override func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -143,7 +136,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
|
||||
- parameter object: the `NSManagedObject` type to be deleted
|
||||
*/
|
||||
public override func delete(_ object: NSManagedObject?) {
|
||||
public override func delete<T: DynamicObject>(_ object: T?) {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -160,7 +153,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
- parameter object2: another `NSManagedObject` type to be deleted
|
||||
- parameter objects: other `NSManagedObject`s type to be deleted
|
||||
*/
|
||||
public override func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
|
||||
public override func delete<T: DynamicObject>(_ object1: T?, _ object2: T?, _ objects: T?...) {
|
||||
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
@@ -188,47 +181,93 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
|
||||
|
||||
self.closure = closure
|
||||
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue) {
|
||||
|
||||
super.init(mainContext: mainContext, queue: queue, supportsUndo: false, bypassesQueueing: false)
|
||||
}
|
||||
|
||||
internal func perform() {
|
||||
internal func autoCommit(_ completion: @escaping (_ hasChanges: Bool, _ error: CoreStoreError?) -> Void) {
|
||||
|
||||
self.transactionQueue.async {
|
||||
self.isCommitted = true
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
|
||||
|
||||
self.closure(self)
|
||||
if !self.isCommitted && self.hasChanges {
|
||||
completion(result.0, result.1)
|
||||
self.result = result
|
||||
group.leave()
|
||||
}
|
||||
group.wait()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Saves the transaction changes. This method should not be used after the `commit()` method was already called once.
|
||||
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new auto-commiting methods `DataStack.perform(asynchronous:completion:)` or `DataStack.perform(asynchronous:success:failure:)`. Please read the documentation on the behavior of the new methods.")
|
||||
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||
)
|
||||
self.autoCommit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
CoreStore.log(
|
||||
.warning,
|
||||
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
|
||||
)
|
||||
case (let hasChanges, nil): completion(SaveResult(hasChanges: hasChanges))
|
||||
case (_, let error?): completion(SaveResult(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal func performAndWait() -> SaveResult? {
|
||||
/**
|
||||
Begins a child transaction synchronously where NSManagedObject creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@available(*, deprecated, message: "Secondary tasks spawned from AsynchronousDataTransactions and SynchronousDataTransactions are no longer supported. ")
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
|
||||
|
||||
self.transactionQueue.sync {
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.cs_isCurrentExecutionContext(),
|
||||
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to begin a child transaction from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
let childTransaction = SynchronousDataTransaction(
|
||||
mainContext: self.context,
|
||||
queue: self.childTransactionQueue
|
||||
)
|
||||
childTransaction.transactionQueue.cs_sync {
|
||||
|
||||
self.closure(self)
|
||||
closure(childTransaction)
|
||||
|
||||
if !self.isCommitted && self.hasChanges {
|
||||
if !childTransaction.isCommitted && childTransaction.hasChanges {
|
||||
|
||||
CoreStore.log(
|
||||
.warning,
|
||||
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
|
||||
message: "The closure for the \(cs_typeName(childTransaction)) completed without being committed. All changes made within the transaction were discarded."
|
||||
)
|
||||
}
|
||||
}
|
||||
return self.result
|
||||
switch childTransaction.result {
|
||||
|
||||
case nil: return nil
|
||||
case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges)
|
||||
case (_, let error?)?: return SaveResult(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let closure: (_ transaction: AsynchronousDataTransaction) -> Void
|
||||
}
|
||||
@@ -39,9 +39,9 @@ public 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<T>(
|
||||
public func importObject<T: DynamicObject & ImportableObject>(
|
||||
_ into: Into<T>,
|
||||
source: T.ImportSource) throws -> T? where T: NSManagedObject, T: ImportableObject {
|
||||
source: T.ImportSource) throws -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -50,8 +50,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
@@ -70,9 +69,9 @@ public extension BaseDataTransaction {
|
||||
- parameter source: the object to import values from
|
||||
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
||||
*/
|
||||
public func importObject<T>(
|
||||
public func importObject<T: DynamicObject & ImportableObject>(
|
||||
_ object: T,
|
||||
source: T.ImportSource) throws where T: NSManagedObject, T: ImportableObject {
|
||||
source: T.ImportSource) throws {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -98,9 +97,9 @@ public extension BaseDataTransaction {
|
||||
- throws: an `Error` thrown from any of the `ImportableObject` methods
|
||||
- returns: the array of created `ImportableObject` instances
|
||||
*/
|
||||
public func importObjects<T, S: Sequence>(
|
||||
public func importObjects<T: DynamicObject & ImportableObject, S: Sequence>(
|
||||
_ into: Into<T>,
|
||||
sourceArray: S) throws -> [T] where T: NSManagedObject, T: ImportableObject, S.Iterator.Element == T.ImportSource {
|
||||
sourceArray: S) throws -> [T] where S.Iterator.Element == T.ImportSource {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -111,7 +110,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try sourceArray.flatMap { (source) -> T? in
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
let entityType = into.entityClass
|
||||
guard entityType.shouldInsert(from: source, in: self) else {
|
||||
|
||||
return nil
|
||||
@@ -134,9 +133,9 @@ public 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<T>(
|
||||
public func importUniqueObject<T: DynamicObject & ImportableUniqueObject>(
|
||||
_ into: Into<T>,
|
||||
source: T.ImportSource) throws -> T? where T: NSManagedObject, T: ImportableUniqueObject {
|
||||
source: T.ImportSource) throws -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -145,7 +144,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
let entityType = into.entityClass
|
||||
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
|
||||
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
|
||||
|
||||
@@ -186,10 +185,10 @@ public extension BaseDataTransaction {
|
||||
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
|
||||
- returns: the array of created/updated `ImportableUniqueObject` instances
|
||||
*/
|
||||
public func importUniqueObjects<T, S: Sequence>(
|
||||
public func importUniqueObjects<T: DynamicObject & ImportableUniqueObject, S: Sequence>(
|
||||
_ into: Into<T>,
|
||||
sourceArray: S,
|
||||
preProcess: @escaping (_ mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] where T: NSManagedObject, T: ImportableUniqueObject, S.Iterator.Element == T.ImportSource {
|
||||
preProcess: @escaping (_ mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] where S.Iterator.Element == T.ImportSource {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -198,7 +197,7 @@ public extension BaseDataTransaction {
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
let entityType = into.entityClass as! T.Type
|
||||
let entityType = into.entityClass
|
||||
var importSourceByID = Dictionary<T.UniqueIDType, T.ImportSource>()
|
||||
let sortedIDs = try autoreleasepool {
|
||||
|
||||
@@ -39,7 +39,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `NSManagedObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<T: NSManagedObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -57,7 +57,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- returns: the number of `NSManagedObject`s deleted
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteAll<T: NSManagedObject>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -76,7 +76,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter object: a reference to the object created/fetched outside the transaction
|
||||
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(_ object: T) -> T? {
|
||||
public func fetchExisting<T: DynamicObject>(_ object: T) -> T? {
|
||||
|
||||
return self.context.fetchExisting(object)
|
||||
}
|
||||
@@ -87,7 +87,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(_ objectID: NSManagedObjectID) -> T? {
|
||||
public func fetchExisting<T: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
return self.context.fetchExisting(objectID)
|
||||
}
|
||||
@@ -98,7 +98,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter objects: an array of `NSManagedObject`s created/fetched outside the transaction
|
||||
- returns: the `NSManagedObject` array for objects that exists in the transaction
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
|
||||
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
|
||||
|
||||
return self.context.fetchExisting(objects)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `NSManagedObject` array for objects that exists in the transaction
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
|
||||
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
return self.context.fetchExisting(objectIDs)
|
||||
}
|
||||
@@ -121,7 +121,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -137,7 +137,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -153,7 +153,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchAll<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -169,7 +169,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchAll<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -185,7 +185,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchCount<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -201,7 +201,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchCount<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -217,7 +217,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectID<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -233,7 +233,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectID<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -249,7 +249,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectIDs<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -265,7 +265,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public func fetchObjectIDs<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -287,7 +287,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -306,7 +306,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -325,7 +325,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryAttributes<T: NSManagedObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -344,7 +344,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public func queryAttributes<T: NSManagedObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -359,8 +359,17 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
|
||||
/**
|
||||
The internal `NSManagedObjectContext` managed by this instance. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
|
||||
*/
|
||||
public func internalContext() -> NSManagedObjectContext {
|
||||
public func unsafeContext() -> NSManagedObjectContext {
|
||||
|
||||
return self.context
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "unsafeContext()")
|
||||
public func internalContext() -> NSManagedObjectContext {
|
||||
|
||||
return self.unsafeContext()
|
||||
}
|
||||
}
|
||||
@@ -45,32 +45,36 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a new `NSManagedObject` with the specified entity type.
|
||||
Creates a new `NSManagedObject` or `CoreStoreObject` with the specified entity type.
|
||||
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` instance of the specified entity type.
|
||||
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
|
||||
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
|
||||
*/
|
||||
public func create<T: NSManagedObject>(_ into: Into<T>) -> T {
|
||||
public func create<T: DynamicObject>(_ into: Into<T>) -> T {
|
||||
|
||||
let entityClass = (into.entityClass as! T.Type)
|
||||
let entityClass = into.entityClass
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
|
||||
)
|
||||
|
||||
let context = self.context
|
||||
let dataStack = context.parentStack!
|
||||
let entityIdentifier = EntityIdentifier(entityClass)
|
||||
if into.inferStoreIfPossible {
|
||||
|
||||
switch context.parentStack!.persistentStoreForEntityClass(
|
||||
entityClass,
|
||||
switch dataStack.persistentStore(
|
||||
for: entityIdentifier,
|
||||
configuration: nil,
|
||||
inferStoreIfPossible: true
|
||||
) {
|
||||
|
||||
case (let persistentStore?, _):
|
||||
let object = entityClass.createInContext(context)
|
||||
context.assign(object, to: persistentStore)
|
||||
return object
|
||||
return entityClass.cs_forceCreate(
|
||||
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
|
||||
into: context,
|
||||
assignTo: persistentStore
|
||||
)
|
||||
|
||||
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.")
|
||||
@@ -81,17 +85,19 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
}
|
||||
else {
|
||||
|
||||
switch context.parentStack!.persistentStoreForEntityClass(
|
||||
entityClass,
|
||||
switch dataStack.persistentStore(
|
||||
for: entityIdentifier,
|
||||
configuration: into.configuration
|
||||
?? type(of: into).defaultConfigurationName,
|
||||
?? DataStack.defaultConfigurationName,
|
||||
inferStoreIfPossible: false
|
||||
) {
|
||||
|
||||
case (let persistentStore?, _):
|
||||
let object = entityClass.createInContext(context)
|
||||
context.assign(object, to: persistentStore)
|
||||
return object
|
||||
return entityClass.cs_forceCreate(
|
||||
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
|
||||
into: context,
|
||||
assignTo: persistentStore
|
||||
)
|
||||
|
||||
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.")
|
||||
@@ -115,7 +121,7 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter object: the `NSManagedObject` type to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
||||
*/
|
||||
public func edit<T: NSManagedObject>(_ object: T?) -> T? {
|
||||
public func edit<T: DynamicObject>(_ object: T?) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -135,7 +141,7 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object to be edited
|
||||
- returns: an editable proxy for the specified `NSManagedObject`.
|
||||
*/
|
||||
public func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
public func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
@@ -143,10 +149,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
)
|
||||
CoreStore.assert(
|
||||
into.inferStoreIfPossible
|
||||
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
|
||||
|| (into.configuration ?? DataStack.defaultConfigurationName) == objectID.persistentStore?.configurationName,
|
||||
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
|
||||
)
|
||||
return self.fetchExisting(objectID) as? T
|
||||
return self.fetchExisting(objectID)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,17 +160,16 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
|
||||
- parameter object: the `NSManagedObject` to be deleted
|
||||
*/
|
||||
public func delete(_ object: NSManagedObject?) {
|
||||
public func delete<T: DynamicObject>(_ object: T?) {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete an entity outside its designated queue."
|
||||
)
|
||||
guard let object = object else {
|
||||
|
||||
return
|
||||
}
|
||||
self.context.fetchExisting(object)?.deleteFromContext()
|
||||
let context = self.context
|
||||
object
|
||||
.flatMap(context.fetchExisting)
|
||||
.flatMap({ context.delete($0.cs_toRaw()) })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +179,7 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
- parameter object2: another `NSManagedObject` to be deleted
|
||||
- parameter objects: other `NSManagedObject`s to be deleted
|
||||
*/
|
||||
public func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
|
||||
public func delete<T: DynamicObject>(_ object1: T?, _ object2: T?, _ objects: T?...) {
|
||||
|
||||
self.delete(([object1, object2] + objects).flatMap { $0 })
|
||||
}
|
||||
@@ -184,15 +189,14 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
|
||||
- parameter objects: the `NSManagedObject`s to be deleted
|
||||
*/
|
||||
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
|
||||
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
|
||||
|
||||
CoreStore.assert(
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to delete entities outside their designated queue."
|
||||
)
|
||||
|
||||
let context = self.context
|
||||
objects.forEach { context.fetchExisting($0)?.deleteFromContext() }
|
||||
objects.forEach { context.fetchExisting($0).flatMap({ context.delete($0.cs_toRaw()) }) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,7 +208,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
self.isRunningInAllowedQueue(),
|
||||
"Attempted to refresh entities outside their designated queue."
|
||||
)
|
||||
|
||||
self.context.refreshAndMergeAllObjects()
|
||||
}
|
||||
|
||||
@@ -226,7 +229,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return self.context.insertedObjects
|
||||
}
|
||||
|
||||
@@ -246,7 +248,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.insertedObjects.flatMap { $0 as? T })
|
||||
}
|
||||
|
||||
@@ -265,7 +266,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.insertedObjects.map { $0.objectID })
|
||||
}
|
||||
|
||||
@@ -285,7 +285,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.insertedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
|
||||
}
|
||||
|
||||
@@ -304,7 +303,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return self.context.updatedObjects
|
||||
}
|
||||
|
||||
@@ -324,7 +322,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
|
||||
}
|
||||
|
||||
@@ -343,7 +340,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.updatedObjects.map { $0.objectID })
|
||||
}
|
||||
|
||||
@@ -363,7 +359,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
|
||||
}
|
||||
|
||||
@@ -382,7 +377,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return self.context.deletedObjects
|
||||
}
|
||||
|
||||
@@ -402,7 +396,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
|
||||
}
|
||||
|
||||
@@ -422,7 +415,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.deletedObjects.map { $0.objectID })
|
||||
}
|
||||
|
||||
@@ -442,20 +434,34 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
!self.isCommitted,
|
||||
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
|
||||
)
|
||||
|
||||
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
|
||||
}
|
||||
|
||||
|
||||
// MARK: 3rd Party Utilities
|
||||
|
||||
/**
|
||||
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
|
||||
```
|
||||
enum Static {
|
||||
static var myDataKey: Void?
|
||||
}
|
||||
transaction.userInfo[&Static.myDataKey] = myObject
|
||||
```
|
||||
- Important: Do not use this method to store thread-sensitive data.
|
||||
*/
|
||||
private let userInfo = UserInfo()
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal let context: NSManagedObjectContext
|
||||
internal let transactionQueue: DispatchQueue
|
||||
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childtransactionqueue")
|
||||
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childTransactionQueue")
|
||||
internal let supportsUndo: Bool
|
||||
internal let bypassesQueueing: Bool
|
||||
internal var isCommitted = false
|
||||
internal var result: SaveResult?
|
||||
internal var result: (hasChanges: Bool, error: CoreStoreError?)?
|
||||
|
||||
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
|
||||
|
||||
@@ -43,29 +43,22 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
|
||||
*/
|
||||
@objc
|
||||
public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
||||
public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
|
||||
|
||||
self.bridgeToSwift.commit { (result) in
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
|
||||
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.bridgeToSwift.isCommitted,
|
||||
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||
)
|
||||
self.bridgeToSwift.autoCommit { (result) in
|
||||
|
||||
completion?(result.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@objc
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||
switch result {
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
case (_, nil): success?()
|
||||
case (_, let error?): failure?(error.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,6 +152,52 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
super.init(swiftValue as! AsynchronousDataTransaction)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
||||
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new -[CSAsynchronousDataTransaction commitWithSuccess:failure:] method.")
|
||||
@objc
|
||||
public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
|
||||
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.bridgeToSwift.isCommitted,
|
||||
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||
)
|
||||
self.bridgeToSwift.commit { (result) in
|
||||
|
||||
completion?(result.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitWithCompletion:` method was already called once.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@available(*, deprecated, message: "Secondary tasks spawned from CSAsynchronousDataTransactions and CSSynchronousDataTransactions are no longer supported. ")
|
||||
@objc
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(object)
|
||||
return self.bridgeToSwift.context.fetchExisting(object) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objectID)
|
||||
return self.bridgeToSwift.context.fetchExisting(objectID) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +64,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objects)
|
||||
return self.bridgeToSwift.context.fetchExisting(objects) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ public extension CSBaseDataTransaction {
|
||||
@objc
|
||||
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.context.fetchExisting(objectIDs)
|
||||
return self.bridgeToSwift.context.fetchExisting(objectIDs) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,10 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSCoreStore
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension CSCoreStore {
|
||||
|
||||
/**
|
||||
@@ -112,5 +111,3 @@ public extension CSCoreStore {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -44,21 +44,9 @@ public extension CSCoreStore {
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
@objc
|
||||
public static var entityClassesByName: [String: NSManagedObject.Type] {
|
||||
public static func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return CoreStore.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the `defaultStack`'s model.
|
||||
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@objc
|
||||
public static func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
|
||||
|
||||
return CoreStore.entityTypesByName[name]
|
||||
return CoreStore.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,4 +125,30 @@ public extension CSCoreStore {
|
||||
|
||||
return self.defaultStack.addSQLiteStorageAndWait(storage, error: error)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public static var entityClassesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return CoreStore.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the `defaultStack`'s model.
|
||||
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public static func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
|
||||
|
||||
return CoreStore.entityTypesByName[name]
|
||||
}
|
||||
}
|
||||
@@ -38,10 +38,7 @@ public extension CSCoreStore {
|
||||
@objc
|
||||
public static func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
|
||||
|
||||
return CoreStore.beginAsynchronous { (transaction) in
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
}
|
||||
self.defaultStack.beginAsynchronous(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,16 +48,9 @@ public extension CSCoreStore {
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@objc
|
||||
@discardableResult
|
||||
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
|
||||
|
||||
return bridge {
|
||||
|
||||
CoreStore.beginSynchronous { (transaction) in
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
return self.defaultStack.beginSynchronous(closure, error: error)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,4 +91,21 @@ public extension CSCoreStore {
|
||||
|
||||
CoreStore.refreshAndMergeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new +[CSCoreStore beginSynchronous:error:] API that reports failure using an error instance.")
|
||||
@objc
|
||||
@discardableResult
|
||||
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
|
||||
return self.defaultStack.beginSynchronous(closure)
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSDataStack
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension CSDataStack {
|
||||
|
||||
/**
|
||||
@@ -42,10 +41,7 @@ public extension CSDataStack {
|
||||
@objc
|
||||
public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.monitorObject(object)
|
||||
}
|
||||
return self.bridgeToSwift.monitorObject(object).bridgeToObjectiveC
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,18 +62,15 @@ public extension CSDataStack {
|
||||
fetchClauses.contains { $0 is CSOrderBy },
|
||||
"A CSListMonitor requires a CSOrderBy clause."
|
||||
)
|
||||
return bridge {
|
||||
|
||||
ListMonitor(
|
||||
dataStack: self.bridgeToSwift,
|
||||
from: from.bridgeToSwift,
|
||||
sectionBy: nil,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
)
|
||||
}
|
||||
return ListMonitor(
|
||||
dataStack: self.bridgeToSwift,
|
||||
from: from.bridgeToSwift,
|
||||
sectionBy: nil,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
).bridgeToObjectiveC
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,18 +125,15 @@ public extension CSDataStack {
|
||||
fetchClauses.contains { $0 is CSOrderBy },
|
||||
"A CSListMonitor requires an CSOrderBy clause."
|
||||
)
|
||||
return bridge {
|
||||
|
||||
ListMonitor(
|
||||
dataStack: self.bridgeToSwift,
|
||||
from: from.bridgeToSwift,
|
||||
sectionBy: sectionBy.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
)
|
||||
}
|
||||
return ListMonitor(
|
||||
dataStack: self.bridgeToSwift,
|
||||
from: from.bridgeToSwift,
|
||||
sectionBy: sectionBy.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
).bridgeToObjectiveC
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,5 +169,3 @@ public extension CSDataStack {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -40,7 +40,7 @@ public extension CSDataStack {
|
||||
@objc
|
||||
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(object)
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(object) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ public extension CSDataStack {
|
||||
@objc
|
||||
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
|
||||
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(objectID)
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(objectID) as NSManagedObject?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +64,7 @@ public extension CSDataStack {
|
||||
@objc
|
||||
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(objects)
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(objects) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ public extension CSDataStack {
|
||||
@objc
|
||||
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
|
||||
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(objectIDs)
|
||||
return self.bridgeToSwift.mainContext.fetchExisting(objectIDs) as [NSManagedObject]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,27 +38,57 @@ public extension CSDataStack {
|
||||
@objc
|
||||
public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
|
||||
|
||||
return self.bridgeToSwift.beginAsynchronous { (transaction) in
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
}
|
||||
self.bridgeToSwift.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
let csTransaction = transaction.bridgeToObjectiveC
|
||||
closure(csTransaction)
|
||||
if !transaction.isCommitted && transaction.hasChanges {
|
||||
|
||||
CoreStore.log(
|
||||
.warning,
|
||||
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
|
||||
)
|
||||
}
|
||||
try transaction.cancel()
|
||||
},
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
|
||||
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
|
||||
*/
|
||||
@objc
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
|
||||
|
||||
return bridge {
|
||||
return bridge(error) {
|
||||
|
||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||
do {
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
try self.bridgeToSwift.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
let csTransaction = transaction.bridgeToObjectiveC
|
||||
closure(csTransaction)
|
||||
if !transaction.isCommitted && transaction.hasChanges {
|
||||
|
||||
CoreStore.log(
|
||||
.warning,
|
||||
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
|
||||
)
|
||||
}
|
||||
try transaction.cancel()
|
||||
}
|
||||
)
|
||||
}
|
||||
catch CoreStoreError.userCancelled {
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,4 +131,27 @@ public extension CSDataStack {
|
||||
|
||||
self.bridgeToSwift.refreshAndMergeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new -[CSDataStack beginSynchronous:error:] API that reports failure using an error instance.")
|
||||
@objc
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(modelName: String?, bundle: Bundle?, versionChain: [String]?) {
|
||||
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
@@ -73,7 +73,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(modelName: String?, bundle: Bundle?, versionTree: [String: String]?) {
|
||||
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionTree: [String: String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
@@ -84,40 +84,6 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `DataStack` from an `NSManagedObjectModel`.
|
||||
|
||||
- parameter model: the `NSManagedObjectModel` for the stack
|
||||
- parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
model: model,
|
||||
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `DataStack` from an `NSManagedObjectModel`.
|
||||
|
||||
- parameter model: the `NSManagedObjectModel` for the stack
|
||||
- parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
model: model,
|
||||
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
|
||||
*/
|
||||
@@ -128,23 +94,12 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the stack's model.
|
||||
Returns the entity name-to-class type mapping from the `CSDataStack`'s model.
|
||||
*/
|
||||
@objc
|
||||
public var entityClassesByName: [String: NSManagedObject.Type] {
|
||||
public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the stack's's model.
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@objc
|
||||
public func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName[name]
|
||||
return self.bridgeToSwift.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +125,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
return bridge(error) {
|
||||
|
||||
try self.bridgeToSwift.addStorageAndWait(InMemoryStore.self)
|
||||
try self.bridgeToSwift.addStorageAndWait(InMemoryStore())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +143,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
return bridge(error) {
|
||||
|
||||
try self.bridgeToSwift.addStorageAndWait(SQLiteStore.self)
|
||||
try self.bridgeToSwift.addStorageAndWait(SQLiteStore())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +223,67 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
|
||||
self.bridgeToSwift = swiftValue
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Initializes a `DataStack` from an `NSManagedObjectModel`.
|
||||
|
||||
- parameter model: the `NSManagedObjectModel` for the stack
|
||||
- parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
|
||||
@objc
|
||||
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
model: model,
|
||||
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a `DataStack` from an `NSManagedObjectModel`.
|
||||
|
||||
- parameter model: the `NSManagedObjectModel` for the stack
|
||||
- parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the -[initWithModelName:bundle:versionTree:] initializer.")
|
||||
@objc
|
||||
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
|
||||
|
||||
self.init(
|
||||
DataStack(
|
||||
model: model,
|
||||
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the stack's model.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public var entityClassesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity class for the given entity name from the stack's's model.
|
||||
- parameter name: the entity name
|
||||
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
|
||||
@objc
|
||||
public func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
|
||||
|
||||
return self.bridgeToSwift.entityTypesByName[name]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
51
Sources/CSDynamicSchema.swift
Normal file
51
Sources/CSDynamicSchema.swift
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// CSDynamicSchema.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - CSDynamicSchema
|
||||
|
||||
/**
|
||||
The `CSDynamicSchema` serves as the Objective-C bridging type for `DynamicSchema`.
|
||||
|
||||
- SeeAlso: `DynamicSchema`
|
||||
*/
|
||||
@objc
|
||||
public protocol CSDynamicSchema {
|
||||
|
||||
/**
|
||||
The version string for this model schema.
|
||||
*/
|
||||
@objc
|
||||
var modelVersion: ModelVersion { get }
|
||||
|
||||
/**
|
||||
Do not call this directly. The `NSManagedObjectModel` for this schema may be created lazily and using this method directly may affect the integrity of the model.
|
||||
*/
|
||||
@objc
|
||||
func rawModel() -> NSManagedObjectModel
|
||||
}
|
||||
@@ -137,6 +137,16 @@ public enum CSErrorCode: Int {
|
||||
An internal SDK call failed with the specified "NSError" userInfo key.
|
||||
*/
|
||||
case internalError
|
||||
|
||||
/**
|
||||
The transaction was terminated by a user-thrown error with the specified "Error" userInfo key.
|
||||
*/
|
||||
case userError
|
||||
|
||||
/**
|
||||
The transaction was cancelled by the user.
|
||||
*/
|
||||
case userCancelled
|
||||
}
|
||||
|
||||
|
||||
@@ -209,12 +219,23 @@ extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
|
||||
self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
|
||||
|
||||
case .internalError:
|
||||
guard case let NSError as NSError = info["NSError"] else {
|
||||
guard case let nsError as NSError = info["NSError"] else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
self = .internalError(NSError: NSError)
|
||||
self = .internalError(NSError: nsError)
|
||||
|
||||
case .userError:
|
||||
guard case let error as Error = info["Error"] else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
self = .userError(error: error)
|
||||
|
||||
case .userCancelled:
|
||||
self = .userCancelled
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import CoreData
|
||||
- SeeAlso: `From`
|
||||
*/
|
||||
@objc
|
||||
public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
public final class CSFrom: NSObject {
|
||||
|
||||
/**
|
||||
The associated `NSManagedObject` entity class
|
||||
@@ -71,7 +71,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass) {
|
||||
public convenience init(entityClass: NSManagedObject.Type) {
|
||||
|
||||
self.init(From(entityClass))
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass, configuration: Any) {
|
||||
public convenience init(entityClass: NSManagedObject.Type, configuration: Any) {
|
||||
|
||||
switch configuration {
|
||||
|
||||
@@ -111,9 +111,9 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass, configurations: [Any]) {
|
||||
public convenience init(entityClass: NSManagedObject.Type, configurations: [Any]) {
|
||||
|
||||
var arguments = [String?]()
|
||||
var arguments = [ModelConfiguration]()
|
||||
for configuration in configurations {
|
||||
|
||||
switch configuration {
|
||||
@@ -154,7 +154,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - From
|
||||
|
||||
extension From: CoreStoreSwiftType {
|
||||
extension From where T: NSManagedObject {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -162,4 +162,16 @@ extension From: CoreStoreSwiftType {
|
||||
|
||||
return CSFrom(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate func downcast() -> From<NSManagedObject> {
|
||||
|
||||
return From<NSManagedObject>(
|
||||
entityClass: self.entityClass,
|
||||
configurations: self.configurations,
|
||||
findPersistentStores: self.findPersistentStores
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(configuration: String?) {
|
||||
public convenience init(configuration: ModelConfiguration) {
|
||||
|
||||
self.init(InMemoryStore(configuration: configuration))
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
|
||||
The configuration name in the model file
|
||||
*/
|
||||
@objc
|
||||
public var configuration: String? {
|
||||
public var configuration: ModelConfiguration {
|
||||
|
||||
return self.bridgeToSwift.configuration
|
||||
}
|
||||
@@ -35,13 +35,13 @@ import CoreData
|
||||
- SeeAlso: `Into`
|
||||
*/
|
||||
@objc
|
||||
public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
public final class CSInto: NSObject {
|
||||
|
||||
/**
|
||||
The associated `NSManagedObject` entity class
|
||||
*/
|
||||
@objc
|
||||
public var entityClass: AnyClass {
|
||||
public var entityClass: NSManagedObject.Type {
|
||||
|
||||
return self.bridgeToSwift.entityClass
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
|
||||
*/
|
||||
@objc
|
||||
public var configuration: String? {
|
||||
public var configuration: ModelConfiguration {
|
||||
|
||||
return self.bridgeToSwift.configuration
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter entityClass: the `NSManagedObject` class type to be created
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass) {
|
||||
public convenience init(entityClass: NSManagedObject.Type) {
|
||||
|
||||
self.init(Into(entityClass))
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(entityClass: AnyClass, configuration: String?) {
|
||||
public convenience init(entityClass: NSManagedObject.Type, configuration: ModelConfiguration) {
|
||||
|
||||
self.init(Into(entityClass, configuration))
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - Into
|
||||
|
||||
extension Into: CoreStoreSwiftType {
|
||||
extension Into where T: NSManagedObject {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -130,4 +130,16 @@ extension Into: CoreStoreSwiftType {
|
||||
|
||||
return CSInto(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate func downcast() -> Into<NSManagedObject> {
|
||||
|
||||
return Into<NSManagedObject>(
|
||||
entityClass: self.entityClass,
|
||||
configuration: self.configuration,
|
||||
inferStoreIfPossible: self.inferStoreIfPossible
|
||||
)
|
||||
}
|
||||
}
|
||||
109
Sources/CSLegacyXcodeDataModelSchema.swift
Normal file
109
Sources/CSLegacyXcodeDataModelSchema.swift
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// CSLegacyXcodeDataModelSchema.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - CSLegacyXcodeDataModelSchema
|
||||
|
||||
/**
|
||||
The `CSLegacyXcodeDataModelSchema` serves as the Objective-C bridging type for `LegacyXcodeDataModelSchema`.
|
||||
|
||||
- SeeAlso: `LegacyXcodeDataModelSchema`
|
||||
*/
|
||||
@objc
|
||||
public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
|
||||
|
||||
@objc
|
||||
public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
|
||||
|
||||
self.bridgeToSwift = LegacyXcodeDataModelSchema(
|
||||
modelName: modelName,
|
||||
model: model
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: NSObject
|
||||
|
||||
public override var hash: Int {
|
||||
|
||||
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
||||
}
|
||||
|
||||
public override func isEqual(_ object: Any?) -> Bool {
|
||||
|
||||
guard let object = object as? CSLegacyXcodeDataModelSchema else {
|
||||
|
||||
return false
|
||||
}
|
||||
return self.bridgeToSwift === object.bridgeToSwift
|
||||
}
|
||||
|
||||
public override var description: String {
|
||||
|
||||
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
|
||||
}
|
||||
|
||||
|
||||
// MARK: CSDynamicSchema
|
||||
|
||||
@objc
|
||||
public var modelVersion: ModelVersion {
|
||||
|
||||
return self.bridgeToSwift.modelVersion
|
||||
}
|
||||
|
||||
@objc
|
||||
public func rawModel() -> NSManagedObjectModel {
|
||||
|
||||
return self.bridgeToSwift.rawModel()
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
|
||||
public let bridgeToSwift: LegacyXcodeDataModelSchema
|
||||
|
||||
public required init(_ swiftValue: LegacyXcodeDataModelSchema) {
|
||||
|
||||
self.bridgeToSwift = swiftValue
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - LegacyXcodeDataModelSchema
|
||||
|
||||
extension LegacyXcodeDataModelSchema: CoreStoreSwiftType {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
public var bridgeToObjectiveC: CSLegacyXcodeDataModelSchema {
|
||||
|
||||
return CSLegacyXcodeDataModelSchema(self)
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSListMonitor
|
||||
|
||||
/**
|
||||
@@ -36,8 +34,9 @@ import CoreData
|
||||
|
||||
- SeeAlso: `ListMonitor`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
|
||||
public final class CSListMonitor: NSObject {
|
||||
|
||||
// MARK: Public (Accessors)
|
||||
|
||||
@@ -546,7 +545,8 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - ListMonitor
|
||||
|
||||
extension ListMonitor: CoreStoreSwiftType {
|
||||
@available(OSX 10.12, *)
|
||||
extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -554,6 +554,17 @@ extension ListMonitor: CoreStoreSwiftType {
|
||||
|
||||
return CSListMonitor(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate func downcast() -> ListMonitor<NSManagedObject> {
|
||||
|
||||
@inline(__always)
|
||||
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||
|
||||
return unsafeBitCast(x, to: type)
|
||||
}
|
||||
return noWarnUnsafeBitCast(self, to: ListMonitor<NSManagedObject>.self)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSListObserver
|
||||
|
||||
/**
|
||||
@@ -42,6 +40,7 @@ import CoreData
|
||||
|
||||
- SeeAlso: `ListObserver`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public protocol CSListObserver: class, AnyObject {
|
||||
|
||||
@@ -92,6 +91,7 @@ public protocol CSListObserver: class, AnyObject {
|
||||
|
||||
- SeeAlso: `ListObjectObserver`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public protocol CSListObjectObserver: CSListObserver {
|
||||
|
||||
@@ -152,6 +152,7 @@ public protocol CSListObjectObserver: CSListObserver {
|
||||
|
||||
- SeeAlso: `ListSectionObserver`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public protocol CSListSectionObserver: CSListObjectObserver {
|
||||
|
||||
@@ -175,5 +176,3 @@ public protocol CSListSectionObserver: CSListObjectObserver {
|
||||
@objc
|
||||
optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSObjectMonitor
|
||||
|
||||
/**
|
||||
@@ -36,8 +34,9 @@ import CoreData
|
||||
|
||||
- SeeAlso: `ObjectMonitor`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
|
||||
public final class CSObjectMonitor: NSObject {
|
||||
|
||||
/**
|
||||
Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
|
||||
@@ -138,7 +137,8 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - ObjectMonitor
|
||||
|
||||
extension ObjectMonitor: CoreStoreSwiftType {
|
||||
@available(OSX 10.12, *)
|
||||
extension ObjectMonitor where ObjectMonitor.ObjectType: NSManagedObject {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -146,6 +146,17 @@ extension ObjectMonitor: CoreStoreSwiftType {
|
||||
|
||||
return CSObjectMonitor(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
fileprivate func downcast() -> ObjectMonitor<NSManagedObject> {
|
||||
|
||||
@inline(__always)
|
||||
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
|
||||
|
||||
return unsafeBitCast(x, to: type)
|
||||
}
|
||||
return noWarnUnsafeBitCast(self, to: ObjectMonitor<NSManagedObject>.self)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSObjectObserver
|
||||
|
||||
/**
|
||||
@@ -40,6 +38,7 @@ import CoreData
|
||||
|
||||
- SeeAlso: `ObjectObserver`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public protocol CSObjectObserver: class, AnyObject {
|
||||
|
||||
@@ -71,5 +70,3 @@ public protocol CSObjectObserver: class, AnyObject {
|
||||
@objc
|
||||
optional func objectMonitor(_ monitor: CSObjectMonitor, didDeleteObject object: Any)
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -40,19 +40,18 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
/**
|
||||
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
||||
|
||||
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
|
||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(fileURL: URL, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
public convenience init(fileURL: URL, configuration: ModelConfiguration, localStorageOptions: Int) {
|
||||
|
||||
self.init(
|
||||
SQLiteStore(
|
||||
fileURL: fileURL,
|
||||
configuration: configuration,
|
||||
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
|
||||
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
||||
)
|
||||
)
|
||||
@@ -61,29 +60,27 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
/**
|
||||
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
||||
|
||||
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
|
||||
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
|
||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
|
||||
*/
|
||||
@objc
|
||||
public convenience init(fileName: String, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
public convenience init(fileName: String, configuration: ModelConfiguration, localStorageOptions: Int) {
|
||||
|
||||
self.init(
|
||||
SQLiteStore(
|
||||
fileName: fileName,
|
||||
configuration: configuration,
|
||||
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
|
||||
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`.
|
||||
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
|
||||
|
||||
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
|
||||
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||
*/
|
||||
@objc
|
||||
public convenience override init() {
|
||||
@@ -104,12 +101,12 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
}
|
||||
|
||||
/**
|
||||
The `NSBundle`s from which to search mapping models for migrations
|
||||
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
|
||||
*/
|
||||
@objc
|
||||
public var mappingModelBundles: [Bundle] {
|
||||
|
||||
return self.bridgeToSwift.mappingModelBundles
|
||||
public var migrationMappingProviders: [Any] {
|
||||
|
||||
return self.bridgeToSwift.migrationMappingProviders
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +130,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
/**
|
||||
The configuration name in the model file
|
||||
*/
|
||||
public var configuration: String? {
|
||||
public var configuration: ModelConfiguration {
|
||||
|
||||
return self.bridgeToSwift.configuration
|
||||
}
|
||||
@@ -194,6 +191,55 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
|
||||
self.bridgeToSwift = swiftValue
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
||||
|
||||
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
|
||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileURL:configuration:localStorageOptions:]) initializer instead.")
|
||||
@objc
|
||||
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
|
||||
self.init(
|
||||
SQLiteStore(
|
||||
fileURL: fileURL,
|
||||
configuration: configuration,
|
||||
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
|
||||
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
|
||||
|
||||
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
|
||||
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
|
||||
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
|
||||
*/
|
||||
@available(*, deprecated: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileName:configuration:localStorageOptions:]) initializer instead.")
|
||||
@objc
|
||||
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
|
||||
|
||||
self.init(
|
||||
SQLiteStore(
|
||||
fileName: fileName,
|
||||
configuration: configuration,
|
||||
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
|
||||
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import CoreData
|
||||
|
||||
- SeeAlso: `SaveResult`
|
||||
*/
|
||||
@available(*, deprecated, message: "Use APIs that report failures with `CSError`s instead.")
|
||||
@objc
|
||||
public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
@@ -173,6 +174,7 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - SaveResult
|
||||
|
||||
@available(*, deprecated, message: "Use the new DataStack.perform(asynchronous:...) and DataStack.perform(synchronous:...) family of APIs")
|
||||
extension SaveResult: CoreStoreSwiftType {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
@@ -27,8 +27,6 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CSSectionBy
|
||||
|
||||
/**
|
||||
@@ -36,6 +34,7 @@ import CoreData
|
||||
|
||||
- SeeAlso: `SectionBy`
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
@objc
|
||||
public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
@@ -87,6 +86,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
// MARK: - SectionBy
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension SectionBy: CoreStoreSwiftType {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
@@ -96,5 +96,3 @@ extension SectionBy: CoreStoreSwiftType {
|
||||
return CSSectionBy(self)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -359,9 +359,9 @@ public final class CSSelect: NSObject {
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
|
||||
public init<T: SelectValueResultType>(_ swiftValue: Select<T>) {
|
||||
public init<T: QueryableAttributeType>(_ swiftValue: Select<T>) {
|
||||
|
||||
self.attributeType = T.attributeType
|
||||
self.attributeType = T.cs_rawAttributeType
|
||||
self.selectTerms = swiftValue.selectTerms
|
||||
self.bridgeToSwift = swiftValue
|
||||
super.init()
|
||||
@@ -47,7 +47,7 @@ public protocol CSStorageInterface {
|
||||
The configuration name in the model file
|
||||
*/
|
||||
@objc
|
||||
var configuration: String? { get }
|
||||
var configuration: ModelConfiguration { get }
|
||||
|
||||
/**
|
||||
The options dictionary for the `NSPersistentStore`
|
||||
@@ -106,10 +106,10 @@ public protocol CSLocalStorage: CSStorageInterface {
|
||||
var fileURL: URL { get }
|
||||
|
||||
/**
|
||||
The `NSBundle`s from which to search mapping models for migrations
|
||||
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
|
||||
*/
|
||||
@objc
|
||||
var mappingModelBundles: [Bundle] { get }
|
||||
var migrationMappingProviders: [Any] { get }
|
||||
|
||||
/**
|
||||
Options that tell the `CSDataStack` how to setup the persistent store
|
||||
@@ -38,34 +38,19 @@ import CoreData
|
||||
public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWait` method was already called once.
|
||||
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWaitWithError:` method was already called once.
|
||||
|
||||
- returns: a `CSSaveResult` containing the success or failure information
|
||||
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
|
||||
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
|
||||
*/
|
||||
@objc
|
||||
public func commitAndWait() -> CSSaveResult {
|
||||
public func commitAndWait(error: NSErrorPointer) -> Bool {
|
||||
|
||||
return bridge {
|
||||
return bridge(error) {
|
||||
|
||||
self.bridgeToSwift.commitAndWait()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitAndWait` method was already called once.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@objc
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||
if case (_, let error?) = self.bridgeToSwift.context.saveSynchronously(waitForMerge: true) {
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,6 +143,44 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
super.init(swiftValue as! SynchronousDataTransaction)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWait` method was already called once.
|
||||
|
||||
- returns: a `CSSaveResult` containing the success or failure information
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new -[CSSynchronousDataTransaction commitAndWaitWithError:] method")
|
||||
@objc
|
||||
public func commitAndWait() -> CSSaveResult {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.commitAndWait()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitAndWait` method was already called once.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@available(*, deprecated, message: "Secondary tasks spawned from CSAsynchronousDataTransactions and CSSynchronousDataTransactions are no longer supported. ")
|
||||
@objc
|
||||
@discardableResult
|
||||
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
|
||||
|
||||
return bridge {
|
||||
|
||||
self.bridgeToSwift.beginSynchronous { (transaction) in
|
||||
|
||||
closure(transaction.bridgeToObjectiveC)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,32 +36,43 @@ import CoreData
|
||||
*/
|
||||
@objc
|
||||
public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
/**
|
||||
Saves the transaction changes asynchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
|
||||
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `error` argument of the block.
|
||||
*/
|
||||
@objc
|
||||
public func commit(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
||||
public func commitWithSuccess(_ success: (() -> Void)?, _ failure: ((CSError) -> Void)?) {
|
||||
|
||||
self.bridgeToSwift.commit { (result) in
|
||||
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (_, error) in
|
||||
|
||||
completion?(result.bridgeToObjectiveC)
|
||||
if let error = error {
|
||||
|
||||
failure?(error.bridgeToObjectiveC)
|
||||
}
|
||||
else {
|
||||
|
||||
success?()
|
||||
}
|
||||
withExtendedLifetime(self, {})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
|
||||
|
||||
- returns: a `CSSaveResult` containing the success or failure information
|
||||
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
|
||||
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
|
||||
*/
|
||||
@objc
|
||||
public func commitAndWait() -> CSSaveResult {
|
||||
public func commitAndWait(error: NSErrorPointer) -> Bool {
|
||||
|
||||
return bridge {
|
||||
return bridge(error) {
|
||||
|
||||
self.bridgeToSwift.commitAndWait()
|
||||
if case (_, let error?) = self.bridgeToSwift.context.saveSynchronously(waitForMerge: true) {
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +167,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
- that all saves will be done either through the `CSUnsafeDataTransaction`'s `-commit:` or `-commitAndWait` method, or by calling `-save:` manually on the context, its parent, and all other ancestor contexts if there are any.
|
||||
*/
|
||||
@objc
|
||||
public var internalContext: NSManagedObjectContext {
|
||||
public func unsafeContext() -> NSManagedObjectContext {
|
||||
|
||||
return self.bridgeToSwift.context
|
||||
}
|
||||
@@ -188,6 +199,58 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
|
||||
|
||||
super.init(swiftValue as! UnsafeDataTransaction)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@available(*, deprecated, renamed: "unsafeContext()")
|
||||
@objc
|
||||
public var internalContext: NSManagedObjectContext {
|
||||
|
||||
return self.bridgeToSwift.context
|
||||
}
|
||||
|
||||
/**
|
||||
Saves the transaction changes asynchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
|
||||
|
||||
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new -[CSUnsafeDataTransaction commitWithSuccess:failure:] method")
|
||||
@objc
|
||||
public func commit(_ completion: ((_ result: CSSaveResult) -> Void)?) {
|
||||
|
||||
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (hasChanges, error) in
|
||||
|
||||
if let error = error {
|
||||
|
||||
completion?(SaveResult(error).bridgeToObjectiveC)
|
||||
}
|
||||
else {
|
||||
|
||||
completion?(SaveResult(hasChanges: hasChanges).bridgeToObjectiveC)
|
||||
}
|
||||
withExtendedLifetime(self, {})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
|
||||
|
||||
- returns: a `CSSaveResult` containing the success or failure information
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new -[CSUnsafeDataTransaction commitAndWaitWithError:] method")
|
||||
@objc
|
||||
public func commitAndWait() -> CSSaveResult {
|
||||
|
||||
return bridge { () -> SaveResult in
|
||||
|
||||
switch self.bridgeToSwift.context.saveSynchronously(waitForMerge: true) {
|
||||
|
||||
case (let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
|
||||
case (_, let error?): return SaveResult(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,11 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
||||
- parameter value: the arguments for the `==` operator
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPath: KeyPath, isEqualTo value: NSObject?) {
|
||||
public convenience init(keyPath: KeyPath, isEqualTo value: CoreDataNativeType?) {
|
||||
|
||||
self.init(Where(keyPath, isEqualTo: value))
|
||||
self.init(value == nil || value is NSNull
|
||||
? Where("\(keyPath) == nil")
|
||||
: Where("\(keyPath) == %@", value!))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +99,9 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
|
||||
- parameter list: the array to check membership of
|
||||
*/
|
||||
@objc
|
||||
public convenience init(keyPath: KeyPath, isMemberOf list: [NSObject]) {
|
||||
public convenience init(keyPath: KeyPath, isMemberOf list: [CoreDataNativeType]) {
|
||||
|
||||
self.init(Where(keyPath, isMemberOf: list))
|
||||
self.init(Where("\(keyPath) IN %@", list as NSArray))
|
||||
}
|
||||
|
||||
/**
|
||||
109
Sources/CSXcodeDataModelSchema.swift
Normal file
109
Sources/CSXcodeDataModelSchema.swift
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// CSXcodeDataModelSchema.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - CSXcodeDataModelSchema
|
||||
|
||||
/**
|
||||
The `CSXcodeDataModelSchema` serves as the Objective-C bridging type for `XcodeDataModelSchema`.
|
||||
|
||||
- SeeAlso: `XcodeDataModelSchema`
|
||||
*/
|
||||
@objc
|
||||
public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
|
||||
|
||||
@objc
|
||||
public required init(modelName: ModelVersion, modelVersionFileURL: URL) {
|
||||
|
||||
self.bridgeToSwift = XcodeDataModelSchema(
|
||||
modelName: modelName,
|
||||
modelVersionFileURL: modelVersionFileURL
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: NSObject
|
||||
|
||||
public override var hash: Int {
|
||||
|
||||
return ObjectIdentifier(self.bridgeToSwift).hashValue
|
||||
}
|
||||
|
||||
public override func isEqual(_ object: Any?) -> Bool {
|
||||
|
||||
guard let object = object as? CSXcodeDataModelSchema else {
|
||||
|
||||
return false
|
||||
}
|
||||
return self.bridgeToSwift === object.bridgeToSwift
|
||||
}
|
||||
|
||||
public override var description: String {
|
||||
|
||||
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
|
||||
}
|
||||
|
||||
|
||||
// MARK: CSDynamicSchema
|
||||
|
||||
@objc
|
||||
public var modelVersion: ModelVersion {
|
||||
|
||||
return self.bridgeToSwift.modelVersion
|
||||
}
|
||||
|
||||
@objc
|
||||
public func rawModel() -> NSManagedObjectModel {
|
||||
|
||||
return self.bridgeToSwift.rawModel()
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreObjectiveCType
|
||||
|
||||
public let bridgeToSwift: XcodeDataModelSchema
|
||||
|
||||
public required init(_ swiftValue: XcodeDataModelSchema) {
|
||||
|
||||
self.bridgeToSwift = swiftValue
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - XcodeDataModelSchema
|
||||
|
||||
extension XcodeDataModelSchema: CoreStoreSwiftType {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
public var bridgeToObjectiveC: CSXcodeDataModelSchema {
|
||||
|
||||
return CSXcodeDataModelSchema(self)
|
||||
}
|
||||
}
|
||||
81
Sources/CoreDataNativeType.swift
Normal file
81
Sources/CoreDataNativeType.swift
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// CoreDataNativeType.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - CoreDataNativeType
|
||||
|
||||
/**
|
||||
Objective-C Foundation types that are natively supported by Core Data managed attributes all conform to `CoreDataNativeType`.
|
||||
*/
|
||||
@objc
|
||||
public protocol CoreDataNativeType: class, NSObjectProtocol, AnyObject {}
|
||||
|
||||
|
||||
// MARK: - NSNumber
|
||||
|
||||
extension NSNumber: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSString
|
||||
|
||||
extension NSString: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSDate
|
||||
|
||||
extension NSDate: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSData
|
||||
|
||||
extension NSData: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSSet
|
||||
|
||||
extension NSSet: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSOrderedSet
|
||||
|
||||
extension NSOrderedSet: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSManagedObject
|
||||
|
||||
extension NSManagedObject: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSManagedObjectID
|
||||
|
||||
extension NSManagedObjectID: CoreDataNativeType {}
|
||||
|
||||
|
||||
// MARK: - NSNull
|
||||
|
||||
extension NSNull: CoreDataNativeType {}
|
||||
@@ -48,8 +48,7 @@ extension AsynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDe
|
||||
("context", self.context),
|
||||
("supportsUndo", self.supportsUndo),
|
||||
("bypassesQueueing", self.bypassesQueueing),
|
||||
("isCommitted", self.isCommitted),
|
||||
("result", self.result as Any)
|
||||
("isCommitted", self.isCommitted)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -142,6 +141,13 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
|
||||
case .internalError(let NSError):
|
||||
firstLine = ".internalError"
|
||||
info.append(("NSError", NSError))
|
||||
|
||||
case .userError(error: let error):
|
||||
firstLine = ".userError"
|
||||
info.append(("Error", error))
|
||||
|
||||
case .userCancelled:
|
||||
firstLine = ".userCancelled"
|
||||
}
|
||||
|
||||
return createFormattedString(
|
||||
@@ -152,6 +158,32 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CoreStoreSchema
|
||||
|
||||
extension CoreStoreSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return createFormattedString(
|
||||
"(", ")",
|
||||
("modelVersion", self.modelVersion),
|
||||
("entitiesByConfiguration", self.entitiesByConfiguration),
|
||||
("rawModel", self.rawModel())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - DataStack
|
||||
|
||||
extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
@@ -173,14 +205,38 @@ extension DataStack: CustomDebugStringConvertible, CoreStoreDebugStringConvertib
|
||||
("coordinator", self.coordinator),
|
||||
("rootSavingContext", self.rootSavingContext),
|
||||
("mainContext", self.mainContext),
|
||||
("model", self.model),
|
||||
("migrationChain", self.migrationChain),
|
||||
("schemaHistory", self.schemaHistory),
|
||||
("coordinator.persistentStores", self.coordinator.persistentStores)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Entity
|
||||
|
||||
extension Entity: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return createFormattedString(
|
||||
"(", ")",
|
||||
("type", self.type),
|
||||
("entityName", self.entityName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - From
|
||||
|
||||
extension From: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
@@ -316,9 +372,9 @@ extension Into: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - LegacySQLiteStore
|
||||
// MARK: - LegacyXcodeDataModelSchema
|
||||
|
||||
extension LegacySQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
extension LegacyXcodeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
@@ -334,20 +390,16 @@ extension LegacySQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringC
|
||||
|
||||
return createFormattedString(
|
||||
"(", ")",
|
||||
("configuration", self.configuration as Any),
|
||||
("storeOptions", self.storeOptions as Any),
|
||||
("fileURL", self.fileURL),
|
||||
("mappingModelBundles", self.mappingModelBundles),
|
||||
("localStorageOptions", self.localStorageOptions)
|
||||
("modelVersion", self.modelVersion),
|
||||
("rawModel", self.rawModel())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ListMonitor
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertible {
|
||||
|
||||
let sectionInfo: NSFetchedResultsSectionInfo
|
||||
@@ -362,6 +414,7 @@ private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertib
|
||||
}
|
||||
}
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension ListMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
@@ -384,7 +437,6 @@ extension ListMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvert
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - LocalStorageOptions
|
||||
@@ -451,7 +503,7 @@ extension MigrationChain: CustomDebugStringConvertible, CoreStoreDebugStringConv
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
guard self.valid else {
|
||||
guard self.isValid else {
|
||||
|
||||
return "<invalid migration chain>"
|
||||
}
|
||||
@@ -554,10 +606,9 @@ extension MigrationType: CustomDebugStringConvertible, CoreStoreDebugStringConve
|
||||
}
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - ObjectMonitor
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
@@ -579,7 +630,7 @@ extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConve
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - OrderBy
|
||||
|
||||
@@ -607,6 +658,7 @@ extension OrderBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertible
|
||||
|
||||
// MARK: - SaveResult
|
||||
|
||||
@available(*, deprecated, message: "Use the new DataStack.perform(asynchronous:...) and DataStack.perform(synchronous:...) family of APIs")
|
||||
extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
@@ -639,10 +691,9 @@ extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConverti
|
||||
}
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - SectionBy
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
extension SectionBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
@@ -663,7 +714,32 @@ extension SectionBy: CustomDebugStringConvertible, CoreStoreDebugStringConvertib
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: - SchemaHistory
|
||||
|
||||
extension SchemaHistory: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return createFormattedString(
|
||||
"(", ")",
|
||||
("currentModelVersion", self.currentModelVersion),
|
||||
("migrationChain", self.migrationChain),
|
||||
("schemaByVersion", self.schemaByVersion)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Select
|
||||
@@ -789,7 +865,7 @@ extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvert
|
||||
("configuration", self.configuration as Any),
|
||||
("storeOptions", self.storeOptions as Any),
|
||||
("fileURL", self.fileURL),
|
||||
("mappingModelBundles", self.mappingModelBundles),
|
||||
("migrationMappingProviders", self.migrationMappingProviders),
|
||||
("localStorageOptions", self.localStorageOptions)
|
||||
)
|
||||
}
|
||||
@@ -817,8 +893,7 @@ extension SynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDeb
|
||||
("context", self.context),
|
||||
("supportsUndo", self.supportsUndo),
|
||||
("bypassesQueueing", self.bypassesQueueing),
|
||||
("isCommitted", self.isCommitted),
|
||||
("result", self.result as Any)
|
||||
("isCommitted", self.isCommitted)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -894,6 +969,80 @@ extension Where: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - VersionLock
|
||||
|
||||
extension VersionLock: CustomStringConvertible, CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
|
||||
var string = "["
|
||||
if self.hashesByEntityName.isEmpty {
|
||||
|
||||
string.append(":]")
|
||||
return string
|
||||
}
|
||||
for (index, keyValue) in self.hashesByEntityName.enumerated() {
|
||||
|
||||
let data = keyValue.value
|
||||
let count = data.count
|
||||
let bytes = data.withUnsafeBytes { (pointer: UnsafePointer<HashElement>) in
|
||||
|
||||
return (0 ..< (count / MemoryLayout<HashElement>.size))
|
||||
.map({ "\("0x\(String(pointer[$0], radix: 16, uppercase: false))")" })
|
||||
}
|
||||
string.append("\(index == 0 ? "\n" : ",\n")\"\(keyValue.key)\": [\(bytes.joined(separator: ", "))]")
|
||||
}
|
||||
string.indent(1)
|
||||
string.append("\n]")
|
||||
return string
|
||||
}
|
||||
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return self.description
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - XcodeDataModelSchema
|
||||
|
||||
extension XcodeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return createFormattedString(
|
||||
"(", ")",
|
||||
("modelVersion", self.modelVersion),
|
||||
("modelVersionFileURL", self.modelVersionFileURL),
|
||||
("rawModel", self.rawModel())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private: Utilities
|
||||
|
||||
private typealias DumpInfo = [(key: String, value: Any)]
|
||||
@@ -970,7 +1119,7 @@ public protocol CoreStoreDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private:
|
||||
// MARK: - Standard Types:
|
||||
|
||||
extension Array: CoreStoreDebugStringConvertible {
|
||||
|
||||
@@ -1212,7 +1361,15 @@ extension NSSortDescriptor: CoreStoreDebugStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension URL: CoreStoreDebugStringConvertible {
|
||||
extension NSString: CoreStoreDebugStringConvertible {
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return "\"\(self)\""
|
||||
}
|
||||
}
|
||||
|
||||
extension NSURL: CoreStoreDebugStringConvertible {
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
@@ -1247,3 +1404,11 @@ extension String: CoreStoreDebugStringConvertible {
|
||||
return "\"\(self)\""
|
||||
}
|
||||
}
|
||||
|
||||
extension URL: CoreStoreDebugStringConvertible {
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return "\"\(self)\""
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ public extension CoreStore {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
@inline(__always)
|
||||
internal static func log(_ level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
|
||||
self.logger.log(
|
||||
@@ -49,6 +50,7 @@ public extension CoreStore {
|
||||
)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func log(_ error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
|
||||
self.logger.log(
|
||||
@@ -60,7 +62,8 @@ public extension CoreStore {
|
||||
)
|
||||
}
|
||||
|
||||
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
@inline(__always)
|
||||
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
|
||||
self.logger.assert(
|
||||
condition,
|
||||
@@ -71,6 +74,7 @@ public extension CoreStore {
|
||||
)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal static func abort(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) -> Never {
|
||||
|
||||
self.logger.abort(
|
||||
@@ -30,27 +30,6 @@ import CoreData
|
||||
// MARK: - CoreStore
|
||||
|
||||
public extension CoreStore {
|
||||
|
||||
/**
|
||||
Asynchronously adds a `StorageInterface` with default settings to the `defaultStack`. Migrations are also initiated by default.
|
||||
```
|
||||
CoreStore.addStorage(
|
||||
InMemoryStore.self,
|
||||
completion: { result in
|
||||
switch result {
|
||||
case .success(let storage): // ...
|
||||
case .failure(let error): // ...
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
- parameter storeType: the storage type
|
||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
public static func addStorage<T: StorageInterface>(_ storeType: T.Type, completion: @escaping (SetupResult<T>) -> Void) where T: DefaultInitializableStore {
|
||||
|
||||
self.defaultStack.addStorage(storeType.init(), completion: completion)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously adds a `StorageInterface` to the `defaultStack`. Migrations are also initiated by default.
|
||||
@@ -72,28 +51,6 @@ public extension CoreStore {
|
||||
|
||||
self.defaultStack.addStorage(storage, completion: completion)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously adds a `LocalStorage` with default settings to the `defaultStack`. Migrations are also initiated by default.
|
||||
```
|
||||
let migrationProgress = CoreStore.addStorage(
|
||||
SQLiteStore.self,
|
||||
completion: { result in
|
||||
switch result {
|
||||
case .success(let storage): // ...
|
||||
case .failure(let error): // ...
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
- parameter storeType: the local storage type
|
||||
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
||||
- returns: a `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
|
||||
*/
|
||||
public static func addStorage<T: LocalStorage>(_ storeType: T.Type, completion: @escaping (SetupResult<T>) -> Void) -> Progress? where T: DefaultInitializableStore {
|
||||
|
||||
return self.defaultStack.addStorage(storeType.init(), completion: completion)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously adds a `LocalStorage` to the `defaultStack`. Migrations are also initiated by default.
|
||||
@@ -27,10 +27,9 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CoreStore
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public extension CoreStore {
|
||||
|
||||
/**
|
||||
@@ -39,7 +38,7 @@ public extension CoreStore {
|
||||
- parameter object: the `NSManagedObject` to observe changes from
|
||||
- returns: a `ObjectMonitor` that monitors changes to `object`
|
||||
*/
|
||||
public static func monitorObject<T: NSManagedObject>(_ object: T) -> ObjectMonitor<T> {
|
||||
public static func monitorObject<T: DynamicObject>(_ object: T) -> ObjectMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorObject(object)
|
||||
}
|
||||
@@ -51,7 +50,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public static func monitorList<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public static func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorList(from, fetchClauses)
|
||||
}
|
||||
@@ -63,7 +62,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public static func monitorList<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public static func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorList(from, fetchClauses)
|
||||
}
|
||||
@@ -75,7 +74,7 @@ public extension CoreStore {
|
||||
- parameter from: a `From` clause indicating the entity type
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public static func monitorList<T: NSManagedObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
|
||||
public static func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||
}
|
||||
@@ -87,7 +86,7 @@ public extension CoreStore {
|
||||
- parameter from: a `From` clause indicating the entity type
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public static func monitorList<T: NSManagedObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
|
||||
public static func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||
}
|
||||
@@ -100,7 +99,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public static func monitorSectionedList<T: NSManagedObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public static func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -113,7 +112,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public static func monitorSectionedList<T: NSManagedObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public static func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -126,7 +125,7 @@ public extension CoreStore {
|
||||
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public static func monitorSectionedList<T: NSManagedObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
|
||||
public static func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
|
||||
|
||||
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
@@ -139,10 +138,8 @@ public extension CoreStore {
|
||||
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
*/
|
||||
public static func monitorSectionedList<T: NSManagedObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
|
||||
public static func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
|
||||
|
||||
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -37,7 +37,7 @@ public extension CoreStore {
|
||||
- parameter object: a reference to the object created/fetched outside the `DataStack`
|
||||
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject>(_ object: T) -> T? {
|
||||
public static func fetchExisting<T: DynamicObject>(_ object: T) -> T? {
|
||||
|
||||
return self.defaultStack.fetchExisting(object)
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public extension CoreStore {
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject>(_ objectID: NSManagedObjectID) -> T? {
|
||||
public static func fetchExisting<T: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
return self.defaultStack.fetchExisting(objectID)
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public extension CoreStore {
|
||||
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
|
||||
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
|
||||
public static func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
|
||||
|
||||
return self.defaultStack.fetchExisting(objects)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public extension CoreStore {
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
|
||||
public static func fetchExisting<T: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
|
||||
|
||||
return self.defaultStack.fetchExisting(objectIDs)
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
public static func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
return self.defaultStack.fetchOne(from, fetchClauses)
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchOne<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
public static func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
return self.defaultStack.fetchOne(from, fetchClauses)
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchAll<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
public static func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
return self.defaultStack.fetchAll(from, fetchClauses)
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchAll<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
public static func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
return self.defaultStack.fetchAll(from, fetchClauses)
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchCount<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
public static func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
return self.defaultStack.fetchCount(from, fetchClauses)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchCount<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
public static func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
return self.defaultStack.fetchCount(from, fetchClauses)
|
||||
}
|
||||
@@ -154,7 +154,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectID<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
public static func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
return self.defaultStack.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectID<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
public static func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
return self.defaultStack.fetchObjectID(from, fetchClauses)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectIDs<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
public static func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
|
||||
*/
|
||||
public static func fetchObjectIDs<T: NSManagedObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
public static func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
public static func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
return self.defaultStack.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -220,7 +220,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
public static func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
return self.defaultStack.queryValue(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -235,7 +235,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryAttributes<T: NSManagedObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
public static func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
|
||||
|
||||
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -250,7 +250,7 @@ public extension CoreStore {
|
||||
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
|
||||
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
|
||||
*/
|
||||
public static func queryAttributes<T: NSManagedObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
public static func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
|
||||
|
||||
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import CoreData
|
||||
public extension CoreStore {
|
||||
|
||||
/**
|
||||
Returns the `defaultStack`'s model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
|
||||
Returns the `defaultStack`'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 {
|
||||
|
||||
@@ -42,9 +42,17 @@ public extension CoreStore {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
public static var entityTypesByName: [String: NSManagedObject.Type] {
|
||||
public static func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.defaultStack.entityTypesByName
|
||||
return self.defaultStack.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
public static func entityTypesByName(for type: CoreStoreObject.Type) -> [EntityName: CoreStoreObject.Type] {
|
||||
|
||||
return self.defaultStack.entityTypesByName(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +63,14 @@ public extension CoreStore {
|
||||
return self.defaultStack.entityDescription(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `CoreStoreObject` subclass from `defaultStack`'s model.
|
||||
*/
|
||||
public static func entityDescription(for type: CoreStoreObject.Type) -> NSEntityDescription? {
|
||||
|
||||
return self.defaultStack.entityDescription(for: type)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an `SQLiteStore` with default parameters and adds it to the `defaultStack`. This method blocks until completion.
|
||||
```
|
||||
@@ -65,22 +81,7 @@ public extension CoreStore {
|
||||
@discardableResult
|
||||
public static func addStorageAndWait() throws -> SQLiteStore {
|
||||
|
||||
return try self.defaultStack.addStorageAndWait(SQLiteStore.self)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `StorageInterface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
|
||||
```
|
||||
try CoreStore.addStorageAndWait(InMemoryStore.self)
|
||||
```
|
||||
- parameter storeType: the `StorageInterface` type
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: the `StorageInterface` added to the `defaultStack`
|
||||
*/
|
||||
@discardableResult
|
||||
public static func addStorageAndWait<T: StorageInterface>(_ storeType: T.Type) throws -> T where T: DefaultInitializableStore {
|
||||
|
||||
return try self.defaultStack.addStorageAndWait(storeType.init())
|
||||
return try self.defaultStack.addStorageAndWait(SQLiteStore())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,21 +99,6 @@ public extension CoreStore {
|
||||
return try self.defaultStack.addStorageAndWait(storage)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `LocalStorageInterface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
|
||||
```
|
||||
try CoreStore.addStorageAndWait(SQLiteStore.self)
|
||||
```
|
||||
- parameter storeType: the `LocalStorageInterface` type
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: the local storage added to the `defaultStack`
|
||||
*/
|
||||
@discardableResult
|
||||
public static func addStorageAndWait<T: LocalStorage>(_ storageType: T.Type) throws -> T where T: DefaultInitializableStore {
|
||||
|
||||
return try self.defaultStack.addStorageAndWait(storageType.init())
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a `LocalStorage` to the `defaultStack` and blocks until completion.
|
||||
```
|
||||
@@ -158,9 +144,18 @@ public extension CoreStore {
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
@available(*, deprecated: 3.0.0, renamed: "entityDescription(for:)")
|
||||
@available(*, deprecated: 3.1, message: "Use the new CoreStore.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
|
||||
public static var entityTypesByName: [EntityName: NSManagedObject.Type] {
|
||||
|
||||
return self.defaultStack.entityTypesByName
|
||||
}
|
||||
|
||||
|
||||
// MARK: Obsolete
|
||||
|
||||
@available(*, obsoleted: 3.1, renamed: "entityDescription(for:)")
|
||||
public static func entityDescriptionForType(_ type: NSManagedObject.Type) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescription(for: type)
|
||||
114
Sources/CoreStore+Transaction.swift
Normal file
114
Sources/CoreStore+Transaction.swift
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// CoreStore+Transaction.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2015 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - CoreStore
|
||||
|
||||
public extension CoreStore {
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` 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 `TransactionResult.success(userInfo: T)` in the `completion`'s `TransactionResult<T>`. Any errors thrown from inside the `task` will be reported as `TransactionResult.failure(error: Error)`. To cancel/rollback changes, call `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 `TransactionResult` 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 `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)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` 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 `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`.
|
||||
- parameter failure: the closure executed if the save fails or if any errors are thrown within `task`. Cancelled `task`s will be indicated by `CoreStoreError.userCancelled`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
|
||||
*/
|
||||
public 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)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, performs a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be rethrown from `perform(synchronous:)`. To cancel/rollback changes, call `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`.
|
||||
- throws: a `CoreStoreError` value indicating the failure. Cancelled `task`s will be indicated by `CoreStoreError.userCancelled`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
|
||||
- returns: the value returned from `task`
|
||||
*/
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, begins a non-contiguous transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. An unsafe transaction object should typically be only used from the main queue.
|
||||
|
||||
- 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)
|
||||
}
|
||||
|
||||
/**
|
||||
Refreshes all registered objects `NSManagedObject`s in the `defaultStack`.
|
||||
*/
|
||||
public static func refreshAndMergeAllObjects() {
|
||||
|
||||
self.defaultStack.refreshAndMergeAllObjects()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, begins a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new auto-commiting methods `perform(asynchronous:completion:)` or `perform(asynchronous:success:failure:)`. Please read the documentation on the behavior of the new methods.")
|
||||
public static func beginAsynchronous(_ closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
|
||||
|
||||
self.defaultStack.beginAsynchronous(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, begins a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made.
|
||||
|
||||
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
|
||||
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
|
||||
*/
|
||||
@available(*, deprecated, message: "Use the new auto-commiting method `perform(synchronous:)`. Please read the documentation on the behavior of the new methods.")
|
||||
@discardableResult
|
||||
public static func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
|
||||
|
||||
return self.defaultStack.beginSynchronous(closure)
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,11 @@ internal func bridge<T: CoreStoreSwiftType>(_ closure: () -> T) -> T.ObjectiveCT
|
||||
return closure().bridgeToObjectiveC
|
||||
}
|
||||
|
||||
internal func bridge<T: CoreStoreSwiftType>(_ closure: () -> [T]) -> [T.ObjectiveCType] {
|
||||
|
||||
return closure().map { $0.bridgeToObjectiveC }
|
||||
}
|
||||
|
||||
internal func bridge<T: CoreStoreSwiftType>(_ closure: () -> T?) -> T.ObjectiveCType? {
|
||||
|
||||
return closure()?.bridgeToObjectiveC
|
||||
@@ -59,6 +59,16 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
*/
|
||||
case internalError(NSError: NSError)
|
||||
|
||||
/**
|
||||
The transaction was terminated by a user-thrown `Error`.
|
||||
*/
|
||||
case userError(error: Error)
|
||||
|
||||
/**
|
||||
The transaction was cancelled by the user.
|
||||
*/
|
||||
case userCancelled
|
||||
|
||||
|
||||
// MARK: CustomNSError
|
||||
|
||||
@@ -85,6 +95,12 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
|
||||
case .internalError:
|
||||
return CoreStoreErrorCode.internalError.rawValue
|
||||
|
||||
case .userError:
|
||||
return CoreStoreErrorCode.userError.rawValue
|
||||
|
||||
case .userCancelled:
|
||||
return CoreStoreErrorCode.userCancelled.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,10 +128,18 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
"localStoreURL": localStoreURL
|
||||
]
|
||||
|
||||
case .internalError(let NSError):
|
||||
case .internalError(let nsError):
|
||||
return [
|
||||
"NSError": NSError
|
||||
"NSError": nsError
|
||||
]
|
||||
|
||||
case .userError(let error):
|
||||
return [
|
||||
"Error": error
|
||||
]
|
||||
|
||||
case .userCancelled:
|
||||
return [:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +163,23 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
return url1 == url2
|
||||
|
||||
case (.internalError(let NSError1), .internalError(let NSError2)):
|
||||
return NSError1 == NSError2
|
||||
return NSError1.isEqual(NSError2)
|
||||
|
||||
case (.userError(let error1), .userError(let error2)):
|
||||
switch (error1, error2) {
|
||||
|
||||
case (let error1 as AnyHashable, let error2 as AnyHashable):
|
||||
return error1 == error2
|
||||
|
||||
case (let error1 as NSError, let error2 as NSError):
|
||||
return error1.isEqual(error2)
|
||||
|
||||
default:
|
||||
return false // shouldn't happen
|
||||
}
|
||||
|
||||
case (.userCancelled, .userCancelled):
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
@@ -166,8 +206,14 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
case .progressiveMigrationRequired(let localStoreURL):
|
||||
return code.hashValue ^ localStoreURL.hashValue
|
||||
|
||||
case .internalError(let NSError):
|
||||
return code.hashValue ^ NSError.hashValue
|
||||
case .internalError(let nsError):
|
||||
return code.hashValue ^ nsError.hashValue
|
||||
|
||||
case .userError(let error):
|
||||
return code.hashValue ^ (error as NSError).hashValue
|
||||
|
||||
case .userCancelled:
|
||||
return code.hashValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +222,7 @@ public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
|
||||
internal init(_ error: Error?) {
|
||||
|
||||
self = error.flatMap { $0.bridgeToSwift } ?? .unknown
|
||||
self = error.flatMap({ $0.bridgeToSwift }) ?? .unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +267,16 @@ public enum CoreStoreErrorCode: Int {
|
||||
An internal SDK call failed with the specified "NSError" userInfo key.
|
||||
*/
|
||||
case internalError
|
||||
|
||||
/**
|
||||
The transaction was terminated by a user-thrown `Error` specified by "Error" userInfo key.
|
||||
*/
|
||||
case userError
|
||||
|
||||
/**
|
||||
The transaction was cancelled by the user.
|
||||
*/
|
||||
case userCancelled
|
||||
}
|
||||
|
||||
|
||||
@@ -232,10 +288,19 @@ public extension NSError {
|
||||
|
||||
internal var isCoreDataMigrationError: Bool {
|
||||
|
||||
let code = self.code
|
||||
return (code == NSPersistentStoreIncompatibleVersionHashError
|
||||
|| code == NSMigrationMissingSourceModelError
|
||||
|| code == NSMigrationError)
|
||||
&& self.domain == NSCocoaErrorDomain
|
||||
guard self.domain == CocoaError.errorDomain else {
|
||||
|
||||
return false
|
||||
}
|
||||
switch CocoaError.Code(rawValue: self.code) {
|
||||
|
||||
case CocoaError.Code.persistentStoreIncompatibleVersionHash,
|
||||
CocoaError.Code.migrationMissingSourceModel,
|
||||
CocoaError.Code.migration:
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ internal extension CoreStoreFetchRequest {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> {
|
||||
|
||||
return unsafeBitCast(self, to: NSFetchRequest<U>.self)
|
||||
@@ -27,16 +27,15 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
// MARK: - CoreStoreFetchedResultsController
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
internal final class CoreStoreFetchedResultsController: NSFetchedResultsController<NSManagedObject> {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc
|
||||
internal convenience init<T: NSManagedObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal convenience init<T: DynamicObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
self.init(
|
||||
context: dataStack.mainContext,
|
||||
@@ -48,7 +47,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal init<T: NSManagedObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
internal init<T: DynamicObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
|
||||
|
||||
_ = from?.applyToFetchRequest(
|
||||
fetchRequest,
|
||||
@@ -66,7 +65,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
}
|
||||
else {
|
||||
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap(From.init) else {
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap({ From<T>($0 as! T.Type) }) else {
|
||||
|
||||
CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From<T>.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
|
||||
}
|
||||
@@ -115,5 +114,3 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
@nonobjc
|
||||
private let reapplyAffectedStores: (_ fetchRequest: NSFetchRequest<NSManagedObject>, _ context: NSManagedObjectContext) -> Bool
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -50,7 +50,8 @@ public protocol CoreStoreLogger {
|
||||
/**
|
||||
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false` if not implemented.
|
||||
*/
|
||||
var enableObjectConcurrencyDebugging: Bool { get set }
|
||||
// TODO: test before release (rolled back)
|
||||
// var enableObjectConcurrencyDebugging: Bool { get set }
|
||||
|
||||
/**
|
||||
Handles log messages sent by the `CoreStore` framework.
|
||||
@@ -99,11 +100,12 @@ public protocol CoreStoreLogger {
|
||||
|
||||
extension CoreStoreLogger {
|
||||
|
||||
public var enableObjectConcurrencyDebugging: Bool {
|
||||
|
||||
get { return false }
|
||||
set {}
|
||||
}
|
||||
// TODO: test before release (rolled back)
|
||||
// public var enableObjectConcurrencyDebugging: Bool {
|
||||
//
|
||||
// get { return false }
|
||||
// set {}
|
||||
// }
|
||||
|
||||
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
99
Sources/CoreStoreObject+Convenience.swift
Normal file
99
Sources/CoreStoreObject+Convenience.swift
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// CoreStoreObject+Convenience.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - CoreStoreObject
|
||||
|
||||
public extension CoreStoreObject {
|
||||
|
||||
/**
|
||||
Exposes a `FetchableSource` that can fetch sibling objects of this `CoreStoreObject` instance. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the obejct's parent is already deallocated.
|
||||
- Warning: Future implementations may change the instance returned by this method depending on the timing or condition that `fetchSource()` was called. Do not make assumptions that the instance will be a specific instance. If the `NSManagedObjectContext` instance is desired, use the `FetchableSource.unsafeContext()` method to get the correct instance. Also, do not assume that the `fetchSource()` and `querySource()` return the same instance all the time.
|
||||
- returns: a `FetchableSource` that can fetch sibling objects of this `CoreStoreObject` instance. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the object's parent is already deallocated.
|
||||
*/
|
||||
@nonobjc
|
||||
public func fetchSource() -> FetchableSource? {
|
||||
|
||||
guard let context = self.rawObject!.managedObjectContext else {
|
||||
|
||||
return nil
|
||||
}
|
||||
if context.isTransactionContext {
|
||||
|
||||
return context.parentTransaction
|
||||
}
|
||||
if context.isDataStackContext {
|
||||
|
||||
return context.parentStack
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
Exposes a `QueryableSource` that can query attributes and aggregate values. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the obejct's parent is already deallocated.
|
||||
- Warning: Future implementations may change the instance returned by this method depending on the timing or condition that `querySource()` was called. Do not make assumptions that the instance will be a specific instance. If the `NSManagedObjectContext` instance is desired, use the `QueryableSource.unsafeContext()` method to get the correct instance. Also, do not assume that the `fetchSource()` and `querySource()` return the same instance all the time.
|
||||
- returns: a `QueryableSource` that can query attributes and aggregate values. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the object's parent is already deallocated.
|
||||
*/
|
||||
@nonobjc
|
||||
public func querySource() -> QueryableSource? {
|
||||
|
||||
guard let context = self.rawObject!.managedObjectContext else {
|
||||
|
||||
return nil
|
||||
}
|
||||
if context.isTransactionContext {
|
||||
|
||||
return context.parentTransaction
|
||||
}
|
||||
if context.isDataStackContext {
|
||||
|
||||
return context.parentStack
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
Re-faults the object to use the latest values from the persistent store
|
||||
*/
|
||||
@nonobjc
|
||||
public func refreshAsFault() {
|
||||
|
||||
let rawObject = self.rawObject!
|
||||
rawObject.managedObjectContext?.refresh(rawObject, mergeChanges: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Re-faults the object to use the latest values from the persistent store and merges previously pending changes back
|
||||
*/
|
||||
@nonobjc
|
||||
public func refreshAndMerge() {
|
||||
|
||||
let rawObject = self.rawObject!
|
||||
rawObject.managedObjectContext?.refresh(rawObject, mergeChanges: true)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user