Compare commits

...

212 Commits

Author SHA1 Message Date
John Rommel Estropia
4b9fddad6a Merge branch 'develop' 2017-12-29 01:09:07 +09:00
John Rommel Estropia
fbe7bd7bf8 update podfile 2017-12-29 00:53:48 +09:00
John Rommel Estropia
15edabdbb5 changed keyPath string utility to use String initializer 2017-12-29 00:05:11 +09:00
John Rommel Estropia
f447bcfb95 Merge branch 'develop' into prototype/Swift_4_0
# Conflicts:
#	CoreStore.podspec
#	Sources/DataStack+Migration.swift
#	Sources/Info.plist
2017-11-19 15:35:29 +09:00
John Rommel Estropia
15e5e4fdf6 delete shm file after converting to DELETE journal mode 2017-11-19 15:34:09 +09:00
John Rommel Estropia
583c6b7249 minor code cleanup 2017-11-19 13:49:21 +09:00
John Rommel Estropia
18b933957e version bump 2017-11-16 02:28:18 +09:00
John Rommel Estropia
2c7039232e merge sqlite journal files before migration 2017-11-16 02:27:06 +09:00
John Rommel Estropia
d3b3b5ff4a added fake progress for lightweight migrations 2017-11-16 02:26:56 +09:00
John Rommel Estropia
d90e8d1303 force true lightweight migration 2017-11-16 02:26:44 +09:00
John Rommel Estropia
b55dd13dff merge sqlite journal files before migration 2017-11-15 23:50:10 +09:00
John Rommel Estropia
66dd5b6f27 added fake progress for lightweight migrations 2017-11-13 02:44:26 +09:00
John Estropia
49c4b770eb WIP: Readme 2017-11-10 19:19:48 +09:00
John Rommel Estropia
662aaa1e75 force true lightweight migration 2017-11-10 02:48:37 +09:00
John Rommel Estropia
dd4e47d7f9 revert null overloads, remove optional objectIDs as condition 2017-11-09 23:26:53 +09:00
John Estropia
9ea5073bc8 Merge branch 'master' into prototype/Swift_4_0
# Conflicts:
#	CoreStore.podspec
#	Sources/Info.plist
2017-11-09 19:52:29 +09:00
John Estropia
e314db8f56 version bump 2017-11-09 19:45:21 +09:00
John Estropia
48d936d068 Fix regression for ARC bugfix (fixes #221) 2017-11-09 19:44:27 +09:00
John Estropia
b2ff8a15ef add query overloads to == so comparison with nil don't confuse the compiler 2017-11-09 19:27:56 +09:00
John Estropia
8a4d1cd7c6 fix demo app warnings 2017-11-09 19:27:05 +09:00
John Rommel Estropia
8ce26c213d more source docs, deprecated some Where clause utilities 2017-11-04 10:37:54 +09:00
John Estropia
f3816b9abf update for Xcode 9.1 2017-11-01 19:49:42 +09:00
John Estropia
21961780d4 force dynamic typing on DynamicObject.Type to mitigate optimization issues 2017-11-01 19:38:38 +09:00
John Rommel Estropia
305e2b61a0 fix compile errors for Xcode 9.1 beta 2017-11-01 19:37:53 +09:00
John Estropia
0430f66240 force dynamic typing on DynamicObject.Type to mitigate optimization issues 2017-11-01 11:33:41 +09:00
John Estropia
65772edd00 Merge pull request #208 from volodg/prototype/Swift_4_0
(Xcode 9.1) fix compile error:
2017-10-29 18:55:13 +09:00
John Rommel Estropia
02d7870d75 fix compile errors for Xcode 9.1 beta 2017-10-29 15:20:58 +09:00
John Rommel Estropia
aca1709e13 WIP: documentation 2017-10-29 15:06:57 +09:00
John Rommel Estropia
b6ee0b014f WIP: documentations 2017-10-24 00:31:27 +09:00
John Estropia
e37186da73 Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0
# Conflicts:
#	CoreStore.podspec
#	Sources/Info.plist
2017-10-17 13:42:04 +09:00
John Estropia
588fa35c84 version bump 2017-10-17 13:39:57 +09:00
John Estropia
f6614cda66 Merge branch 'develop' 2017-10-17 13:39:20 +09:00
John Estropia
639574d8c2 remove inline casts because optimized builds seem to trip on them 2017-10-17 13:38:25 +09:00
John Rommel Estropia
094703155c Merge branch 'master' into prototype/Swift_4_0
# Conflicts:
#	.swift-version
2017-10-13 08:14:20 +09:00
John Rommel Estropia
6dd254e713 Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0
# Conflicts:
#	CoreStore.podspec
#	Sources/Info.plist
2017-10-13 08:10:56 +09:00
John Rommel Estropia
204025721c version bump 2017-10-13 08:10:26 +09:00
John Rommel Estropia
27ffc1d225 Merge branch 'develop'
# Conflicts:
#	CoreStore.podspec
#	Sources/Info.plist
2017-10-13 08:01:30 +09:00
John Rommel Estropia
ba6f0c39d5 swift version 3.2 2017-10-13 08:00:39 +09:00
John Rommel Estropia
ab2eac8f6c Swift 3.2 README update 2017-10-13 07:58:37 +09:00
John Rommel Estropia
f460a0b30f CI: test demo app 2017-10-12 01:10:08 +09:00
John Rommel Estropia
50bc3ace06 travis 2017-10-12 00:02:39 +09:00
John Rommel Estropia
d2ddf2002f version update 2017-10-11 22:40:27 +09:00
John Rommel Estropia
b4117eeb02 updated documentation (fixes #198) 2017-10-11 07:50:24 +09:00
Vladimir
106275b2dd fix compile error:
inheritance from 'AnyObject'
2017-10-07 12:21:27 +08:00
John Rommel Estropia
08d9298be0 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders
# Conflicts:
#	Sources/OrderBy.swift
2017-10-07 01:13:30 +09:00
John Rommel Estropia
ff0c4d94fc Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-10-07 01:10:28 +09:00
John Rommel Estropia
50e50c0613 Merge branch 'develop' into prototype/Swift_3_2 2017-10-07 01:07:09 +09:00
John Rommel Estropia
5c8a0e425b version bump 2017-10-07 00:59:37 +09:00
John Rommel Estropia
03b71caf7e Merge branch 'develop' 2017-10-07 00:58:04 +09:00
John Rommel Estropia
7ff29d6086 version bump 2017-10-07 00:57:41 +09:00
John Rommel Estropia
8d86425875 always create subclass type from cs_rawObject 2017-10-07 00:56:19 +09:00
John Estropia
97242d9726 added type-erasers for CoreStoreObject property containers 2017-10-02 12:00:45 +09:00
John Estropia
780ff4e60b fix compile errors 2017-10-02 11:10:28 +09:00
John Estropia
11743dfb5f oops 2017-10-02 11:08:44 +09:00
John Estropia
9eaf85388c relax generic type requirements for some Where utilities 2017-10-02 10:33:59 +09:00
John Rommel Estropia
06635c9d2f orderby utilities 2017-10-02 08:04:28 +09:00
John Rommel Estropia
1d2eef7894 revert 2017-10-01 01:01:10 +09:00
John Rommel Estropia
85ed815ec2 WIP: more chain clause builder utilities 2017-10-01 00:45:21 +09:00
John Estropia
096e5493a6 WIP: protocol cleanup 2017-09-29 20:33:10 +09:00
John Estropia
0aa8c03424 Merge pull request #205 from jannon/case-insensitive-orderby
add case-insensitive sortkeys
2017-09-29 19:38:36 +09:00
John Estropia
4ead3c34dd delete errant operator 2017-09-26 11:59:28 +09:00
John Rommel Estropia
645034dde5 keyPath utilities for SectionBy clauses 2017-09-24 10:38:17 +09:00
John Rommel Estropia
85706a3c57 version bump 2017-09-22 23:43:19 +09:00
John Rommel Estropia
c5ae4606b9 move cocoapods.yml 2017-09-22 23:41:07 +09:00
John Rommel Estropia
fa682215c5 version bump 2017-09-22 23:26:15 +09:00
John Rommel Estropia
e814733ae9 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders
# Conflicts:
#	Sources/DynamicObject.swift
2017-09-22 23:20:16 +09:00
John Rommel Estropia
e2236698fa Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-09-22 23:18:38 +09:00
John Rommel Estropia
be5da632b3 fix segmentation fault 2017-09-22 23:18:25 +09:00
John Estropia
dc73cd6dd9 added a yml file for pod try (#200) 2017-09-22 15:48:02 +09:00
John Rommel Estropia
7beb3bec75 rename methods 2017-09-22 08:02:13 +09:00
Jannon Frank
53100b202d add case-insensitive sortkeys 2017-09-21 11:38:29 -07:00
John Rommel Estropia
cc84b1f8bd minor 2017-09-22 01:00:03 +09:00
John Rommel Estropia
474f52ed2b alow nil comparison for relationship keypaths 2017-09-22 00:30:02 +09:00
John Rommel Estropia
16225fc4c6 allow optionals in relationship keyPaths 2017-09-22 00:20:55 +09:00
John Rommel Estropia
03bb7619da added queryBuilder utilities for clause sequences 2017-09-22 00:08:01 +09:00
John Rommel Estropia
1bfb7451c3 keyPath utilities for Select queries 2017-09-21 07:56:02 +09:00
John Rommel Estropia
3e082d5ed4 queryBuilders for list monitors 2017-09-20 00:45:38 +09:00
John Rommel Estropia
e45d67252c CoreStore querying utilities 2017-09-20 00:24:03 +09:00
John Rommel Estropia
3d427c29c4 added required settings 2017-09-20 00:09:57 +09:00
John Rommel Estropia
1068517b94 Merge branch 'prototype/queryBuilders' of github.com:JohnEstropia/CoreStore into prototype/queryBuilders 2017-09-20 00:02:36 +09:00
John Estropia
0d23ce1598 fix Demo app compiler errors 2017-09-19 16:22:59 +09:00
John Estropia
fd1ce20863 set swift version 2017-09-19 16:04:26 +09:00
John Estropia
2c5fa63f40 revert 2017-09-19 15:55:51 +09:00
John Estropia
78e43a37a5 fix OSX compiler errors 2017-09-19 15:54:15 +09:00
John Rommel Estropia
fde85a9743 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders 2017-09-17 01:15:55 +09:00
John Rommel Estropia
dbbc0adae5 Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-09-17 01:10:11 +09:00
John Rommel Estropia
2a62770552 Merge branch 'develop' into prototype/Swift_3_2 2017-09-10 12:31:30 +09:00
John Rommel Estropia
f436b26e8e allow compound keypaths in Select terms 2017-09-08 01:28:24 +09:00
John Rommel Estropia
c566226747 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders 2017-08-31 23:50:12 +09:00
John Rommel Estropia
cd405e038e updated demo app 2017-08-31 23:00:17 +09:00
John Estropia
92a37053b0 Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-08-31 18:33:28 +09:00
John Estropia
0b57cff27d Merge branch 'develop' into prototype/Swift_3_2
# Conflicts:
#	Sources/DynamicSchema+Convenience.swift
2017-08-31 18:33:12 +09:00
John Estropia
3ebc44b546 optimize redundant casting in printCoreStoreSchema() 2017-08-31 18:28:23 +09:00
John Estropia
68f1027ba7 fix code misuse in readme 2017-08-31 17:55:10 +09:00
John Rommel Estropia
005729be85 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders 2017-08-26 14:29:16 +09:00
John Estropia
8bac4aa901 Fixed Xcode 9 beta 6 errors 2017-08-24 10:11:12 +09:00
John Estropia
da170c7e51 Fixed Xcode 9 beta 6 errors 2017-08-23 18:40:06 +09:00
John Estropia
211e69023e version bump 2017-08-23 12:59:36 +09:00
John Rommel Estropia
2912dcf010 iOS 11 fixed the NSFetchRequest.affectedStores bug 2017-08-23 12:55:02 +09:00
John Rommel Estropia
3e00a3da06 fix demo app errors 2017-08-17 09:24:33 +09:00
John Rommel Estropia
a33e248828 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders
# Conflicts:
#	Sources/NSManagedObjectContext+Querying.swift
2017-08-16 21:09:09 +09:00
John Rommel Estropia
75e14fbbed Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0
# Conflicts:
#	Sources/NSManagedObjectContext+Querying.swift
2017-08-16 21:08:33 +09:00
John Rommel Estropia
9922deac4d Merge branch 'develop' into prototype/Swift_3_2
# Conflicts:
#	Sources/AttributeProtocol.swift
#	Sources/DynamicSchema+Convenience.swift
#	Sources/ImportableAttributeType.swift
#	Sources/Relationship.swift
#	Sources/RelationshipProtocol.swift
#	Sources/Transformable.swift
#	Sources/Value.swift
2017-08-16 21:07:34 +09:00
John Rommel Estropia
86be046c9f updated podspec 2017-08-16 20:43:10 +09:00
John Rommel Estropia
0f10bc3349 version bump 2017-08-16 20:26:22 +09:00
John Rommel Estropia
9685f0aef2 #191 2017-08-16 20:21:26 +09:00
John Estropia
1e51000155 Merge pull request #191 from sidmani/prototype/Swift_4_0
Corrected type-checking in fetchExisting to preserve input type
2017-08-16 20:20:23 +09:00
John Rommel Estropia
3bd459bb1a updated docs 2017-08-16 20:09:09 +09:00
Sid Mani
c89bc3c227 Corrected type-checking in fetchExisting to preserve input type 2017-08-16 00:36:06 -07:00
John Rommel Estropia
0f405a50aa WIP: KeyPath utilities for all clauses 2017-08-10 00:42:29 +09:00
John Estropia
f5e1643ef7 minor cleanup 2017-08-10 00:10:15 +09:00
John Rommel Estropia
f62137fb58 rename file 2017-08-10 00:10:08 +09:00
John Rommel Estropia
37fbedd799 WIP: keypath utilities for all raw clauses 2017-08-09 08:11:41 +09:00
John Rommel Estropia
28b43f33fa Value.Required now requires an "initial:" parameter. For previous CoreStoreObject users, use the appropriate empty value for your existing properties (0 for numeric types, false for Bool, "" for String) 2017-08-08 18:36:25 +09:00
John Rommel Estropia
81a72f29ea Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders 2017-08-08 08:02:17 +09:00
John Rommel Estropia
f7aaf4fb2a Fix compile errors for Xcode 9 beta 5 2017-08-08 08:02:05 +09:00
John Rommel Estropia
a52acf2ebd Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-08-08 07:56:32 +09:00
John Rommel Estropia
74c64619c3 Fix compile error for Xcode 9 beta 5 2017-08-08 07:56:21 +09:00
John Rommel Estropia
4a5bc6450b complete query utilities 2017-08-08 07:36:52 +09:00
John Rommel Estropia
fe69e7c6c4 Merge branch 'prototype/Swift_4_0' into prototype/queryBuilders
# Conflicts:
#	CoreStore.xcodeproj/project.pbxproj
#	Sources/Relationship.swift
#	Sources/Value.swift
2017-08-05 23:02:00 +09:00
John Rommel Estropia
ccf7c62aad Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-08-05 08:25:49 +09:00
John Rommel Estropia
f36cb8af63 iOS 11 fixed the NSFetchRequest.affectedStores bug 2017-08-05 08:25:28 +09:00
John Rommel Estropia
10ccadd96c update demo app 2017-08-05 08:25:03 +09:00
John Rommel Estropia
5c0e78bd53 Deleted EmptyableAttributeType and require "initial" parameter for Value.Required 2017-08-05 00:03:17 +09:00
John Rommel Estropia
8a09688117 Merge branch 'develop' into prototype/Swift_3_2 2017-07-15 21:30:05 +09:00
John Estropia
a366bcf1a3 Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2017-07-11 15:47:20 +09:00
John Rommel Estropia
fcd4be9011 WIP: chained queries for section monitors 2017-07-10 08:23:59 +09:00
John Rommel Estropia
535eb76adc WIP: query chains! 2017-07-09 10:44:53 +09:00
John Rommel Estropia
c6e68ac24f reset transactions' context on deinit to break reference cycles in unsafed many-to-many relationships 2017-07-05 23:32:45 +09:00
John Rommel Estropia
aff966aac9 WIP: Query builders 2017-07-05 08:45:10 +09:00
John Rommel Estropia
32743b3aee Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-07-04 23:16:49 +09:00
John Rommel Estropia
a20ad87583 Merge branch 'develop' into prototype/Swift_3_2 2017-07-04 23:14:06 +09:00
John Estropia
a11915db12 minor cleanup 2017-07-04 12:21:46 +09:00
John Rommel Estropia
961f39a806 add internal utilities to force checkpoint operations on SQLite 2017-07-01 17:05:10 +09:00
John Rommel Estropia
3096cb784c add internal utilities to force checkpoint operations on SQLite 2017-07-01 16:45:11 +09:00
John Rommel Estropia
809aa4ff96 allow querying file size on SQLiteStore 2017-07-01 11:50:23 +09:00
John Estropia
8d926d25ec Merge pull request #177 from blender/feature/optional-where-chaining
Add optional && and || operators to Where clause
2017-06-28 13:32:16 +09:00
Tommaso Piazza
790454f514 Add optional && and || operators to Where clause 2017-06-27 13:58:16 +02:00
John Rommel Estropia
9a38707c58 Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-06-26 00:36:07 +09:00
John Rommel Estropia
fb7e2f7f7f Merge branch 'develop' into prototype/Swift_3_2 2017-06-26 00:34:32 +09:00
John Rommel Estropia
f72efc80b2 added utilities for combining Where arrays and OrderBy arrays 2017-06-24 17:42:56 +09:00
John Estropia
fcda5399da Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-06-23 17:58:49 +09:00
John Estropia
fd3a9b00ec fix FRC breaking again for iOS 8 2017-06-23 17:58:34 +09:00
John Estropia
f56c37f9ee Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-06-23 12:43:20 +09:00
John Estropia
5f5000218a Merge branch 'develop' into prototype/Swift_3_2
# Conflicts:
#	CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift
#	Sources/Value.swift
2017-06-23 12:43:03 +09:00
John Estropia
e8eb309d82 Added source docs on usage of custom getters and setters for CoreStoreObject properties (Value.Required, etc) 2017-06-20 20:32:27 +09:00
John Rommel Estropia
d0c3203e63 force reset contexts after autocommit 2017-06-17 21:50:21 +09:00
John Rommel Estropia
f5b3901caa fix tests and demo app 2017-06-17 02:13:54 +09:00
John Rommel Estropia
1a99fea820 complete PartialObject utilities 2017-06-17 01:55:36 +09:00
John Rommel Estropia
195b60615b added missing utilities 2017-06-16 01:42:09 +09:00
John Rommel Estropia
2c394965b8 remove direct access to CoreStoreObject.primitiveValues and replace PartialObject<O> 2017-06-16 01:02:23 +09:00
John Rommel Estropia
746d697691 WIP: new PartialObject to act as faster KVC wrappers when implementing custom getters and setters for CoreStoreObject 2017-06-15 08:27:08 +09:00
John Estropia
5689158b43 version bump 2017-06-14 21:50:58 +09:00
John Estropia
6fcdf3d011 fix logger demo 2017-06-14 17:43:34 +09:00
John Estropia
e26573c18e converted the Demo app's observer demo to use CoreStoreObject instead of NSManagedObject 2017-06-14 17:39:57 +09:00
John Estropia
801cf8d9f0 Fixed ListMonitor bug for CoreStoreObjects where ListObservers don't get update notifications 2017-06-14 17:37:46 +09:00
John Rommel Estropia
eced8f2e93 fixed compile error on release mode 2017-06-12 22:39:06 +09:00
John Rommel Estropia
3b735d07ec fix merge compile errors 2017-06-11 09:33:25 +09:00
John Rommel Estropia
5eb5476e3a Merge branch 'prototype/Swift_3_2' into prototype/Swift_4_0 2017-06-11 09:17:03 +09:00
John Rommel Estropia
6a42a0054e Merge branch 'develop' into prototype/Swift_3_2
# Conflicts:
#	Sources/CoreStoreManagedObject.swift
#	Sources/CoreStoreSchema.swift
#	Sources/NSEntityDescription+DynamicModel.swift
#	Sources/Value.swift
2017-06-11 09:16:34 +09:00
John Rommel Estropia
8c437e19b8 version bump 2017-06-10 23:19:02 +09:00
John Rommel Estropia
9cd3b6c879 code cleanup 2017-06-10 22:13:32 +09:00
John Rommel Estropia
fe135acbec Improve CoreStoreObjects KVO behavior 2017-06-10 21:02:36 +09:00
John Estropia
997c5bdcfa uniquify subclass names across model versions 2017-06-09 12:47:22 +09:00
John Estropia
23e12c4539 add constraints to Value.Optional and Value.Required native types 2017-06-09 11:30:09 +09:00
John Estropia
ca9798be14 add constraints to Value.Optional and Value.Required native types 2017-06-09 11:29:51 +09:00
John Estropia
6e01a58c85 Swift 4 support 2017-06-09 11:25:28 +09:00
John Estropia
f618617053 work around issue that crashes the Swift 3.2 compiler (fixes #171) 2017-06-08 20:18:50 +09:00
John Rommel Estropia
49b8b9c372 Merge branch 'master' into prototype/Swift_3_2 2017-06-08 08:10:59 +09:00
John Rommel Estropia
129f975d96 version bump 2017-06-08 01:17:39 +09:00
John Rommel Estropia
a2e463e58c Merge branch 'prototype/customMigrationTest' of github.com:JohnEstropia/CoreStore into prototype/customMigrationTest 2017-06-08 01:07:00 +09:00
John Rommel Estropia
5fd50f0e15 fix migration for CoreStoreObject relationships 2017-06-08 01:06:51 +09:00
John Estropia
7f9a915d71 WIP: Swift 3.2 2017-06-07 20:07:43 +09:00
John Estropia
0a81736b7a Merge branch 'develop' into prototype/customMigrationTest 2017-06-07 12:31:42 +09:00
John Estropia
f9b6dd0c6a fix bug when using ObjectMonitor with CoreStoreObjects 2017-06-06 17:40:29 +09:00
John Rommel Estropia
0354401b56 WIP: bugfix for CustomSchemaMappingProvider relationship migration bug 2017-06-06 08:39:59 +09:00
John Rommel Estropia
0304067beb fix ToManyOrdered and ToManyUnordered enumeration crash 2017-06-06 00:49:16 +09:00
John Rommel Estropia
ddd83da434 add Where comparison operators for optional values 2017-06-05 23:09:19 +09:00
John Estropia
fc7df671de Fixes https://bugs.swift.org/browse/SR-4981 2017-06-05 12:45:35 +09:00
John Rommel Estropia
5fde9030c7 use stronger namespace for CoreStoreObject's internal managed object type 2017-06-05 08:03:37 +09:00
John Rommel Estropia
d7b07b3f00 Added alternative way to set keyPathsForValuesAffectingValue(forKey:) for CoreStoreObjects 2017-06-05 01:30:26 +09:00
John Rommel Estropia
ddd1ffb29f added ~= operation to create Where clauses for value arrays 2017-06-03 08:51:52 +09:00
John Rommel Estropia
98094000bb Merge branch 'master' into develop 2017-06-02 23:10:31 +09:00
John Estropia
d5026ef996 Merge branch 'temp/develop' into develop 2017-06-02 19:35:01 +09:00
John Estropia
2cd913b9dd added more utilities for CoreStoreObject meta 2017-06-02 19:34:54 +09:00
John Estropia
ad9520abbc Update README.md 2017-06-02 13:24:15 +09:00
John Estropia
c0fc57d10c Update README.md 2017-06-02 11:34:04 +09:00
John Estropia
0cf4d303e4 Added README sample on how to version CoreStoreObjects 2017-06-02 11:32:48 +09:00
John Rommel Estropia
6de397958a fix demo app warnings 2017-06-02 02:06:47 +09:00
John Rommel Estropia
55292a84dc made mapping modell providers public 2017-06-02 02:03:41 +09:00
John Estropia
981b560d53 test travis ci 2017-05-30 11:14:57 +09:00
John Estropia
c4c4dd55cd test travis build 2017-05-30 11:06:30 +09:00
John Rommel Estropia
1ddbe20c86 Updated README, fixed demo app, and bumped to 4.0.1 2017-05-28 11:37:40 +09:00
John Rommel Estropia
da9e8c1550 disallow "empty" default values on some ImportableAttributeTypes 2017-05-28 10:50:25 +09:00
John Estropia
ef0937fec4 make unit tests happy 2017-05-24 12:15:55 +09:00
John Estropia
35885b40de README done! Welcome to CoreStore 4.0! 2017-05-24 12:05:34 +09:00
John Rommel Estropia
d669569196 WIP: readme 2017-05-24 00:37:32 +09:00
John Rommel Estropia
ae919ff3c8 WIP: readme 2017-05-24 00:35:25 +09:00
John Rommel Estropia
1a7a4690d1 WIP: readme 2017-05-24 00:33:43 +09:00
John Rommel Estropia
b9b96d1a35 WIP: Updating README and other docs. Some minor fixes 2017-05-22 01:27:38 +09:00
John Rommel Estropia
da3a9590ac accept optionals in setValue 2017-05-21 09:38:56 +09:00
John Rommel Estropia
6b3d75bea1 fix fixits 2017-05-21 09:29:34 +09:00
John Rommel Estropia
d44721fef0 fix xcode hints 2017-05-21 09:11:34 +09:00
John Rommel Estropia
3f268e8376 added NSManagedObject.setValue(_:forKvcKey:willSetValue:didSetValue:) 2017-05-21 09:06:29 +09:00
John Rommel Estropia
303fea4ebe fix warnings 2017-05-21 08:51:38 +09:00
John Estropia
77173cdad0 minor fix 2017-05-18 21:10:43 +09:00
John Estropia
1e24a7d739 ListObserver's listMonitorDidChange(_:) and listMonitorDidRefetch(_:) handlers are now required. 2017-05-18 12:59:58 +09:00
John Estropia
a3b33bedb8 added more migration error types 2017-05-18 12:59:02 +09:00
John Estropia
eaf7544c50 fix error when CoreStoreObject types have deep namespaces 2017-05-17 15:55:33 +09:00
John Estropia
67863120e0 WIP: readme 2017-05-15 11:03:21 +09:00
John Estropia
1b0e305d9a beta bump 2017-05-15 10:23:55 +09:00
John Rommel Estropia
91fda01071 WIP: readme 2017-05-15 08:51:31 +09:00
167 changed files with 11195 additions and 4976 deletions

2
.cocoapods.yml Normal file
View File

@@ -0,0 +1,2 @@
try:
project: 'CoreStore.xcworkspace'

View File

@@ -1 +1 @@
3.1
4.0

View File

@@ -1,5 +1,5 @@
language: objective-c
osx_image: xcode8.3
osx_image: xcode9
sudo: false
git:
submodules: false
@@ -9,25 +9,30 @@ env:
global:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
matrix:
- DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO"
matrix:
- DESTINATION="OS=11.0,name=iPhone 8" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.13 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=4.0,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=11.0,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO"
before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.20.1/Carthage.pkg"
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.26.0/Carthage.pkg"
- sudo installer -pkg "Carthage.pkg" -target /
- rm "Carthage.pkg"
- npm install ios-sim -g
- ios-sim start --devicetypeid "com.apple.CoreSimulator.SimDeviceType.iPhone-8, 11.0"
before_script:
- carthage update --use-submodules
script:
@@ -38,8 +43,8 @@ script:
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
fi
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
- if [ $POD_LINT == "YES" ]; then
pod lib lint --quick;
fi

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "CoreStore"
s.version = "4.0.0-beta"
s.version = "5.0.0"
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"

View File

@@ -34,7 +34,7 @@
82BA18B51C4BBD3F00A0916E /* BaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */; };
82BA18B61C4BBD3F00A0916E /* DataStack+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */; };
82BA18B71C4BBD3F00A0916E /* CoreStore+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */; };
82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
82BA18B81C4BBD4200A0916E /* TypeErasedClauses.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */; };
82BA18B91C4BBD4A00A0916E /* From.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F011AFF847B0064E85B /* From.swift */; };
82BA18BA1C4BBD4A00A0916E /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F031AFF847B0064E85B /* Select.swift */; };
82BA18BB1C4BBD4A00A0916E /* Where.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F051AFF847B0064E85B /* Where.swift */; };
@@ -101,6 +101,18 @@
B51FE5AF1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; };
B5202CFA1C04688100DED140 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
B5215CA41FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA31FA47DFD00139E3A /* FetchChainBuilder.swift */; };
B5215CA51FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA31FA47DFD00139E3A /* FetchChainBuilder.swift */; };
B5215CA61FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA31FA47DFD00139E3A /* FetchChainBuilder.swift */; };
B5215CA71FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA31FA47DFD00139E3A /* FetchChainBuilder.swift */; };
B5215CA91FA4810300139E3A /* QueryChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA81FA4810300139E3A /* QueryChainBuilder.swift */; };
B5215CAA1FA4810300139E3A /* QueryChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA81FA4810300139E3A /* QueryChainBuilder.swift */; };
B5215CAB1FA4810300139E3A /* QueryChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA81FA4810300139E3A /* QueryChainBuilder.swift */; };
B5215CAC1FA4810300139E3A /* QueryChainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CA81FA4810300139E3A /* QueryChainBuilder.swift */; };
B5215CAE1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CAD1FA4812500139E3A /* SectionMonitorBuilder.swift */; };
B5215CAF1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CAD1FA4812500139E3A /* SectionMonitorBuilder.swift */; };
B5215CB01FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CAD1FA4812500139E3A /* SectionMonitorBuilder.swift */; };
B5215CB11FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5215CAD1FA4812500139E3A /* SectionMonitorBuilder.swift */; };
B5220E081D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */; };
B5220E091D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */; };
B5220E0C1D0D0D19009BC71E /* ImportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E0B1D0D0D19009BC71E /* ImportTests.swift */; };
@@ -184,7 +196,7 @@
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */; };
B52DD1A81BE1F93200949AFE /* DataStack+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */; };
B52DD1A91BE1F93200949AFE /* CoreStore+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */; };
B52DD1AA1BE1F93500949AFE /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
B52DD1AA1BE1F93500949AFE /* TypeErasedClauses.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */; };
B52DD1AB1BE1F93900949AFE /* From.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F011AFF847B0064E85B /* From.swift */; };
B52DD1AC1BE1F93900949AFE /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F031AFF847B0064E85B /* Select.swift */; };
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F051AFF847B0064E85B /* Where.swift */; };
@@ -214,10 +226,10 @@
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */; };
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */; };
B52F74411E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74421E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74431E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74441E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */; };
B52F74451E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; };
B52F74461E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; };
B52F74471E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */; };
@@ -238,6 +250,14 @@
B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
B538BA7A1D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; };
B53B275F1EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */; };
B53CA9A21EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
B53CA9A31EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
B53CA9A41EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
B53CA9A51EF1EF1600E0F440 /* PartialObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */; };
B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
@@ -316,6 +336,10 @@
B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */; };
B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */; };
B5519A621CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */; };
B55514EA1EED8BF900BAB888 /* From+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55514E91EED8BF900BAB888 /* From+Querying.swift */; };
B55514EB1EED8BF900BAB888 /* From+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55514E91EED8BF900BAB888 /* From+Querying.swift */; };
B55514EC1EED8BF900BAB888 /* From+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55514E91EED8BF900BAB888 /* From+Querying.swift */; };
B55514ED1EED8BF900BAB888 /* From+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55514E91EED8BF900BAB888 /* From+Querying.swift */; };
B55717441D15B09E009BDBCA /* CoreStoreBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = B55717421D15AF9C009BDBCA /* CoreStoreBridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
B55717451D15B09F009BDBCA /* CoreStoreBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = B55717421D15AF9C009BDBCA /* CoreStoreBridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
B55717461D15B0A1009BDBCA /* CoreStoreBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = B55717421D15AF9C009BDBCA /* CoreStoreBridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -354,7 +378,7 @@
B56321921BD65216006C9394 /* BaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */; };
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */; };
B56321941BD65216006C9394 /* CoreStore+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */; };
B56321951BD65216006C9394 /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
B56321951BD65216006C9394 /* TypeErasedClauses.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */; };
B56321961BD65216006C9394 /* From.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F011AFF847B0064E85B /* From.swift */; };
B56321971BD65216006C9394 /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F031AFF847B0064E85B /* Select.swift */; };
B56321981BD65216006C9394 /* Where.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F051AFF847B0064E85B /* Where.swift */; };
@@ -426,10 +450,10 @@
B56923FB1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; };
B56923FC1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; };
B56923FD1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */; };
B56923FF1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
B56924001EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
B56924011EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
B56924021EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */; };
B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */; };
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; };
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; };
B57D27BE1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */; };
@@ -441,6 +465,18 @@
B580857A1CDF808C004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
B580857B1CDF808D004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
B580857C1CDF808F004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; };
B5831B701F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
B5831B711F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
B5831B721F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
B5831B731F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; };
B5831B751F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; };
B5831B7A1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; };
B58B22F51C93C1BA00521925 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A53019C5C6DA005002A5 /* CoreStore.framework */; };
B58D0C631EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */; };
B58D0C641EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */; };
@@ -465,6 +501,10 @@
B59FA0B01CCBACA7007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; };
B59FA0B11CCBACA7007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; };
B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; };
B5A1DAC81F111BFA003CF369 /* KeyPath+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */; };
B5A1DAC91F111BFA003CF369 /* KeyPath+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */; };
B5A1DACA1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */; };
B5A1DACB1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */; };
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A261201B64BFDB006EB6D3 /* MigrationType.swift */; };
B5A5F2661CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
B5A5F2681CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
@@ -488,6 +528,14 @@
B5C976E71C6E3A5A00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; };
B5CA2B081F7E5ACA004B1936 /* WhereClauseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */; };
B5CA2B091F7E5ACA004B1936 /* WhereClauseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */; };
B5CA2B0A1F7E5ACA004B1936 /* WhereClauseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */; };
B5CA2B0B1F7E5ACA004B1936 /* WhereClauseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */; };
B5CA2B121F81DBFE004B1936 /* DynamicKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B111F81DBFE004B1936 /* DynamicKeyPath.swift */; };
B5CA2B131F81DBFE004B1936 /* DynamicKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B111F81DBFE004B1936 /* DynamicKeyPath.swift */; };
B5CA2B141F81DBFE004B1936 /* DynamicKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B111F81DBFE004B1936 /* DynamicKeyPath.swift */; };
B5CA2B151F81DBFF004B1936 /* DynamicKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CA2B111F81DBFE004B1936 /* DynamicKeyPath.swift */; };
B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; };
B5D339B41E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
B5D339B51E925C2B00C880DE /* DynamicModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */; };
@@ -610,7 +658,7 @@
B5E84F361AFF85470064E85B /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; };
B5E84F371AFF85470064E85B /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
B5E84F411AFF8CCD0064E85B /* TypeErasedClauses.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */; };
B5ECDBDF1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */; };
B5ECDBE11CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */; };
B5ECDBE21CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */; };
@@ -729,6 +777,9 @@
B51260921E9B28F100402229 /* EntityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntityIdentifier.swift; sourceTree = "<group>"; };
B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+CustomDebugStringConvertible.swift"; sourceTree = "<group>"; };
B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.swift"; sourceTree = "<group>"; };
B5215CA31FA47DFD00139E3A /* FetchChainBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchChainBuilder.swift; sourceTree = "<group>"; };
B5215CA81FA4810300139E3A /* QueryChainBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryChainBuilder.swift; sourceTree = "<group>"; };
B5215CAD1FA4812500139E3A /* SectionMonitorBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionMonitorBuilder.swift; sourceTree = "<group>"; };
B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverTests.swift; sourceTree = "<group>"; };
B5220E0B1D0D0D19009BC71E /* ImportTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportTests.swift; sourceTree = "<group>"; };
B5220E0F1D0DA6AB009BC71E /* ListObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListObserverTests.swift; sourceTree = "<group>"; };
@@ -746,12 +797,14 @@
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaHistory.swift; sourceTree = "<group>"; };
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicSchema.swift; sourceTree = "<group>"; };
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyXcodeDataModelSchema.swift; sourceTree = "<group>"; };
B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsafeDataModelSchema.swift; sourceTree = "<group>"; };
B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDataModelSchema.swift; sourceTree = "<group>"; };
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreSchema.swift; sourceTree = "<group>"; };
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; };
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; };
B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; };
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreManagedObject.swift; sourceTree = "<group>"; };
B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartialObject.swift; sourceTree = "<group>"; };
B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationResult.swift; sourceTree = "<group>"; };
B53FBA031CAB300C00F0D40A /* CSMigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationType.swift; sourceTree = "<group>"; };
B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Migrating.swift"; sourceTree = "<group>"; };
@@ -776,6 +829,7 @@
B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSAsynchronousDataTransaction.swift; sourceTree = "<group>"; };
B5548CD51BD65AE00077652A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
B5548CD71BD65AE50077652A /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; };
B55514E91EED8BF900BAB888 /* From+Querying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "From+Querying.swift"; sourceTree = "<group>"; };
B55717421D15AF9C009BDBCA /* CoreStoreBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreStoreBridge.h; sourceTree = "<group>"; };
B559CD421CAA8B6300E4D58B /* CSSetupResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSetupResult.swift; sourceTree = "<group>"; };
B559CD481CAA8C6D00E4D58B /* CSStorageInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSStorageInterface.swift; sourceTree = "<group>"; };
@@ -800,18 +854,22 @@
B56923DF1EB827F5007C4DC9 /* XcodeSchemaMappingProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeSchemaMappingProvider.swift; sourceTree = "<group>"; };
B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSDynamicSchema.swift; sourceTree = "<group>"; };
B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSXcodeDataModelSchema.swift; sourceTree = "<group>"; };
B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSLegacyXcodeDataModelSchema.swift; sourceTree = "<group>"; };
B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSUnsafeDataModelSchema.swift; sourceTree = "<group>"; };
B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "DataStack+Migration.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
B56965231B356B820075EE4A /* MigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationResult.swift; sourceTree = "<group>"; };
B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestDataTestCase.swift; sourceTree = "<group>"; };
B57D27C11D0BC20100539C58 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = "<group>"; };
B58085741CDF7F00004C2EEB /* SetupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetupTests.swift; sourceTree = "<group>"; };
B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributeProtocol.swift; sourceTree = "<group>"; };
B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipProtocol.swift; sourceTree = "<group>"; };
B5831B791F34ACBA00A9F647 /* Transformable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transformable.swift; sourceTree = "<group>"; };
B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+DynamicModel.swift"; sourceTree = "<group>"; };
B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvenienceTests.swift; sourceTree = "<group>"; };
B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchableSource.swift; sourceTree = "<group>"; };
B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryableSource.swift; sourceTree = "<group>"; };
B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSPersistentStoreCoordinator+Setup.swift"; sourceTree = "<group>"; };
B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudStore.swift; sourceTree = "<group>"; };
B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyPath+Querying.swift"; sourceTree = "<group>"; };
B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = "<group>"; };
B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSelect.swift; sourceTree = "<group>"; };
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionLock.swift; sourceTree = "<group>"; };
@@ -822,7 +880,10 @@
B5BDC9271C2024F2008147CD /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = SOURCE_ROOT; };
B5C976E21C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UnsafeDataTransaction+Observing.swift"; sourceTree = "<group>"; };
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreFetchedResultsController.swift; sourceTree = "<group>"; };
B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhereClauseType.swift; sourceTree = "<group>"; };
B5CA2B111F81DBFE004B1936 /* DynamicKeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicKeyPath.swift; sourceTree = "<group>"; };
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreError.swift; sourceTree = "<group>"; };
B5D2D5A91F7558CB00A4DE67 /* .cocoapods.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .cocoapods.yml; sourceTree = SOURCE_ROOT; };
B5D339B31E925C2B00C880DE /* DynamicModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicModelTests.swift; sourceTree = "<group>"; };
B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreObject.swift; sourceTree = "<group>"; };
B5D339DC1E9489C700C880DE /* DynamicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicObject.swift; sourceTree = "<group>"; };
@@ -888,7 +949,7 @@
B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Setup.swift"; sourceTree = "<group>"; };
B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Transaction.swift"; sourceTree = "<group>"; };
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Querying.swift"; sourceTree = "<group>"; };
B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClauseTypes.swift; sourceTree = "<group>"; };
B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeErasedClauses.swift; sourceTree = "<group>"; };
B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSBaseDataTransaction+Querying.swift"; sourceTree = "<group>"; };
B5ECDBE41CA6BEA300C7F112 /* CSClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSClauseTypes.swift; sourceTree = "<group>"; };
B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSFrom.swift; sourceTree = "<group>"; };
@@ -1019,6 +1080,7 @@
B5E84ED91AFF82360064E85B /* LICENSE */,
B5D9C8F61B160ED200E64F0E /* CoreStore.podspec */,
B5BDC91A1C202269008147CD /* Cartfile */,
B5D2D5A91F7558CB00A4DE67 /* .cocoapods.yml */,
B5BDC9271C2024F2008147CD /* .travis.yml */,
B5AD60CD1C90141E00F2B2E8 /* Package.swift */,
);
@@ -1102,13 +1164,24 @@
name = Observing;
sourceTree = "<group>";
};
B5215CA21FA47BF300139E3A /* Chained Clauses */ = {
isa = PBXGroup;
children = (
B55514E91EED8BF900BAB888 /* From+Querying.swift */,
B5215CA31FA47DFD00139E3A /* FetchChainBuilder.swift */,
B5215CA81FA4810300139E3A /* QueryChainBuilder.swift */,
B5215CAD1FA4812500139E3A /* SectionMonitorBuilder.swift */,
);
name = "Chained Clauses";
sourceTree = "<group>";
};
B52F74391E9B8724005F3DAC /* Dynamic Schema */ = {
isa = PBXGroup;
children = (
B52F743A1E9B8724005F3DAC /* DynamicSchema.swift */,
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */,
B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */,
B52F743B1E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift */,
B52F743B1E9B8724005F3DAC /* UnsafeDataModelSchema.swift */,
);
name = "Dynamic Schema";
sourceTree = "<group>";
@@ -1190,7 +1263,7 @@
children = (
B56923F41EB828BF007C4DC9 /* CSDynamicSchema.swift */,
B56923F91EB82956007C4DC9 /* CSXcodeDataModelSchema.swift */,
B56923FE1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift */,
B56923FE1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift */,
);
name = "Dynamic Schema";
sourceTree = "<group>";
@@ -1224,17 +1297,37 @@
isa = PBXGroup;
children = (
B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */,
B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */,
B5831B6E1F3355C300A9F647 /* Properties */,
B52F74391E9B8724005F3DAC /* Dynamic Schema */,
B5D339DC1E9489C700C880DE /* DynamicObject.swift */,
B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */,
B5D339E61E9493A500C880DE /* Entity.swift */,
B5D33A001E96012400C880DE /* Relationship.swift */,
B5D339E11E948C3600C880DE /* Value.swift */,
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */,
);
name = "Dynamic Models";
sourceTree = "<group>";
};
B5831B6E1F3355C300A9F647 /* Properties */ = {
isa = PBXGroup;
children = (
B5D33A001E96012400C880DE /* Relationship.swift */,
B5D339E11E948C3600C880DE /* Value.swift */,
B5831B791F34ACBA00A9F647 /* Transformable.swift */,
);
name = Properties;
sourceTree = "<group>";
};
B5A1DAC61F111BBE003CF369 /* KeyPath Utilities */ = {
isa = PBXGroup;
children = (
B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */,
B5D339EB1E9495E500C880DE /* CoreStoreObject+Querying.swift */,
B5CA2B111F81DBFE004B1936 /* DynamicKeyPath.swift */,
);
name = "KeyPath Utilities";
sourceTree = "<group>";
};
B5A5F26B1CAFF8D0004AB9AF /* Swift */ = {
isa = PBXGroup;
children = (
@@ -1358,13 +1451,14 @@
B5E84EFD1AFF847B0064E85B /* Fetching and Querying */ = {
isa = PBXGroup;
children = (
B5D339EB1E9495E500C880DE /* CoreStoreObject+Querying.swift */,
B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */,
B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */,
B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */,
B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */,
B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */,
B549F65D1E569C7400FBAB2D /* QueryableAttributeType.swift */,
B5215CA21FA47BF300139E3A /* Chained Clauses */,
B5A1DAC61F111BBE003CF369 /* KeyPath Utilities */,
B5E84F0A1AFF847B0064E85B /* Protocol Clauses */,
B5E84EFF1AFF847B0064E85B /* Concrete Clauses */,
);
@@ -1387,7 +1481,8 @@
B5E84F0A1AFF847B0064E85B /* Protocol Clauses */ = {
isa = PBXGroup;
children = (
B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */,
B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */,
B5CA2B071F7E5ACA004B1936 /* WhereClauseType.swift */,
);
name = "Protocol Clauses";
sourceTree = "<group>";
@@ -1423,18 +1518,21 @@
B5E84F291AFF849C0064E85B /* Internal */ = {
isa = PBXGroup;
children = (
B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */,
B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */,
B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */,
B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */,
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
B56923C31EB823B4007C4DC9 /* NSEntityDescription+Migration.swift */,
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */,
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */,
B51260921E9B28F100402229 /* EntityIdentifier.swift */,
B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */,
B5E834BA1B7691F3001D3D50 /* Functions.swift */,
B5FAD6AB1B51285300714891 /* MigrationManager.swift */,
B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */,
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */,
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */,
B51260881E9B252B00402229 /* NSEntityDescription+DynamicModel.swift */,
B56923C31EB823B4007C4DC9 /* NSEntityDescription+Migration.swift */,
B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */,
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */,
B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */,
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */,
B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */,
@@ -1656,32 +1754,32 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0800;
LastUpgradeCheck = 0900;
ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = {
2F03A52F19C5C6DA005002A5 = {
CreatedOnToolsVersion = 6.0;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
2F03A53A19C5C6DA005002A5 = {
CreatedOnToolsVersion = 6.0;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
82BA18881C4BBCBA00A0916E = {
CreatedOnToolsVersion = 7.2;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
82BA18911C4BBCBA00A0916E = {
CreatedOnToolsVersion = 7.2;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
B52DD1731BE1F8CC00949AFE = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
B52DD17C1BE1F8CC00949AFE = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
B563216E1BD65082006C9394 = {
CreatedOnToolsVersion = 7.0.1;
@@ -1771,6 +1869,7 @@
files = (
B5E84F221AFF84860064E85B /* ObjectMonitor.swift in Sources */,
B5ECDBF91CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5CA2B081F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B5C976E71C6E3A5A00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */,
B56923F51EB828BF007C4DC9 /* CSDynamicSchema.swift in Sources */,
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */,
@@ -1782,13 +1881,14 @@
B5D339D81E9489AB00C880DE /* CoreStoreObject.swift in Sources */,
B5D3F6451C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
B56923FA1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
B55514EA1EED8BF900BAB888 /* From+Querying.swift in Sources */,
B596BBBB1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */,
B5ECDC051CA8138100C7F112 /* CSOrderBy.swift in Sources */,
B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A5F1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */,
B52F74411E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A9921F1EA898710091A2E3 /* UserInfo.swift in Sources */,
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
@@ -1802,6 +1902,7 @@
B5ECDC1D1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
B53FBA121CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
B5831B751F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
B5E1B5A81CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */,
@@ -1820,6 +1921,7 @@
B5FAD6AE1B518DCB00714891 /* CoreStore+Migration.swift in Sources */,
B5E84EE71AFF84610064E85B /* CoreStore+Logging.swift in Sources */,
B546F9731C9C553300D5AC55 /* SetupResult.swift in Sources */,
B53CA9A21EF1EF1600E0F440 /* PartialObject.swift in Sources */,
B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */,
B5E84F111AFF847B0064E85B /* Select.swift in Sources */,
B51260931E9B28F100402229 /* EntityIdentifier.swift in Sources */,
@@ -1840,10 +1942,11 @@
B501FDE71CA8D20500BE22EF /* CSListObserver.swift in Sources */,
B5E41EC01EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
B501FDE21CA8D1F500BE22EF /* CSListMonitor.swift in Sources */,
B5A1DAC81F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */,
B5ECDC111CA816E500C7F112 /* CSTweak.swift in Sources */,
B56923C41EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */,
B5E84F411AFF8CCD0064E85B /* TypeErasedClauses.swift in Sources */,
B5E84F0D1AFF847B0064E85B /* BaseDataTransaction+Querying.swift in Sources */,
B52F74451E9B8724005F3DAC /* XcodeDataModelSchema.swift in Sources */,
B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */,
@@ -1868,6 +1971,7 @@
B5E84F0F1AFF847B0064E85B /* From.swift in Sources */,
B5FAD6A91B50A4B400714891 /* Progress+Convenience.swift in Sources */,
B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */,
B5215CA91FA4810300139E3A /* QueryChainBuilder.swift in Sources */,
B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */,
B52F744A1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
@@ -1875,6 +1979,8 @@
B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */,
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
B56923E81EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
B53B275F1EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
B5215CA41FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
B5D33A011E96012400C880DE /* Relationship.swift in Sources */,
B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */,
B56923C91EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
@@ -1892,21 +1998,25 @@
B59FA0AE1CCBAC95007C9BCA /* ICloudStore.swift in Sources */,
B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */,
B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */,
B5831B7A1F34ACBA00A9F647 /* Transformable.swift in Sources */,
B546F9691C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
B53FBA1E1CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */,
B549F65E1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */,
B559CD431CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
B5CA2B121F81DBFE004B1936 /* DynamicKeyPath.swift in Sources */,
B5A991EC1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56923FF1EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
B56923FF1EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B5215CAE1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B56923EC1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */,
B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */,
B53FBA041CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
B5E84EF41AFF846E0064E85B /* AsynchronousDataTransaction.swift in Sources */,
B5831B701F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
B5DBE2CD1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
B546F95D1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
B5D339E71E9493A500C880DE /* Entity.swift in Sources */,
@@ -1955,6 +2065,7 @@
files = (
82BA18B61C4BBD3F00A0916E /* DataStack+Querying.swift in Sources */,
B5ECDBFB1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5CA2B091F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */,
B56923F61EB828BF007C4DC9 /* CSDynamicSchema.swift in Sources */,
82BA18A21C4BBD1D00A0916E /* CoreStoreError.swift in Sources */,
@@ -1966,13 +2077,14 @@
B5D339D91E9489AB00C880DE /* CoreStoreObject.swift in Sources */,
82BA18CE1C4BBD7100A0916E /* FetchedResultsControllerDelegate.swift in Sources */,
B56923FB1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
B55514EB1EED8BF900BAB888 /* From+Querying.swift in Sources */,
B596BBBC1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */,
B5ECDC071CA8138100C7F112 /* CSOrderBy.swift in Sources */,
B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A601CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */,
B52F74421E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */,
B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
@@ -1986,6 +2098,7 @@
B5ECDC1F1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
B5E1B5AA1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
B5D339F21E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
B5D3F6461C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
@@ -2004,6 +2117,7 @@
82BA18A31C4BBD2200A0916E /* DataStack.swift in Sources */,
82BA18C81C4BBD5900A0916E /* MigrationChain.swift in Sources */,
B546F9741C9C553300D5AC55 /* SetupResult.swift in Sources */,
B53CA9A31EF1EF1600E0F440 /* PartialObject.swift in Sources */,
82BA18B11C4BBD3100A0916E /* SaveResult.swift in Sources */,
82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */,
B51260941E9B28F100402229 /* EntityIdentifier.swift in Sources */,
@@ -2024,6 +2138,7 @@
B501FDE91CA8D20500BE22EF /* CSListObserver.swift in Sources */,
B5E41EC11EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
B501FDE41CA8D1F500BE22EF /* CSListMonitor.swift in Sources */,
B5A1DAC91F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
B5FE4DA31C8481E100FA6A91 /* StorageInterface.swift in Sources */,
B5ECDC131CA816E500C7F112 /* CSTweak.swift in Sources */,
B56923C51EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
@@ -2052,6 +2167,7 @@
82BA18C71C4BBD5900A0916E /* CoreStore+Migration.swift in Sources */,
B5E222251CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */,
B5215CAA1FA4810300139E3A /* QueryChainBuilder.swift in Sources */,
82BA18BA1C4BBD4A00A0916E /* Select.swift in Sources */,
B52F744B1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
@@ -2059,6 +2175,8 @@
82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */,
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */,
B56923E91EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
B53B27601EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
B5215CA51FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
B5D33A021E96012400C880DE /* Relationship.swift in Sources */,
B559CD4B1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
B56923CA1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
@@ -2076,21 +2194,25 @@
82BA18D31C4BBD7100A0916E /* NSManagedObjectContext+CoreStore.swift in Sources */,
82BA18AD1C4BBD3100A0916E /* UnsafeDataTransaction.swift in Sources */,
B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */,
B53FBA201CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */,
82BA18A81C4BBD2900A0916E /* CoreStoreLogger.swift in Sources */,
B549F65F1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
B559CD451CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */,
82BA18B81C4BBD4200A0916E /* TypeErasedClauses.swift in Sources */,
B5CA2B131F81DBFE004B1936 /* DynamicKeyPath.swift in Sources */,
B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56924001EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
B56924001EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B5215CAF1FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
B56923ED1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
82BA18B91C4BBD4A00A0916E /* From.swift in Sources */,
B53FBA061CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
82BA18BE1C4BBD4A00A0916E /* Tweak.swift in Sources */,
B5DBE2CE1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
B5831B711F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
B546F95E1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
B5ECDC0D1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
B5D339E81E9493A500C880DE /* Entity.swift in Sources */,
@@ -2139,6 +2261,7 @@
files = (
B5220E1E1D13080D009BC71E /* CSListMonitor.swift in Sources */,
B5DBE2D01C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
B5CA2B0B1F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B5677D411CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */,
B56923F81EB828BF007C4DC9 /* CSDynamicSchema.swift in Sources */,
B52DD1BE1BE1F94300949AFE /* Progress+Convenience.swift in Sources */,
@@ -2150,13 +2273,14 @@
B5D339DB1E9489AB00C880DE /* CoreStoreObject.swift in Sources */,
B52DD1951BE1F92500949AFE /* CoreStoreError.swift in Sources */,
B56923FD1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
B55514ED1EED8BF900BAB888 /* From+Querying.swift in Sources */,
B596BBBE1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
B5ECDC0F1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */,
B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */,
B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */,
B52F74441E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */,
B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */,
@@ -2170,6 +2294,7 @@
B5D3F6481C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
B5220E1C1D130801009BC71E /* FetchedResultsControllerDelegate.swift in Sources */,
B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */,
B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */,
B5D339F41E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
B5220E241D13085E009BC71E /* NSFetchedResultsController+Convenience.swift in Sources */,
@@ -2188,6 +2313,7 @@
B52DD1961BE1F92500949AFE /* DataStack.swift in Sources */,
B5ECDBFD1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */,
B53CA9A51EF1EF1600E0F440 /* PartialObject.swift in Sources */,
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */,
B53FBA1C1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */,
B51260961E9B28F100402229 /* EntityIdentifier.swift in Sources */,
@@ -2208,6 +2334,7 @@
B559CD4D1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
B5E41EC31EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
B5ECDBE91CA6BEA300C7F112 /* CSClauseTypes.swift in Sources */,
B5A1DACB1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
B52DD1B81BE1F94000949AFE /* DataStack+Migration.swift in Sources */,
B5ECDC091CA8138100C7F112 /* CSOrderBy.swift in Sources */,
B56923C71EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
@@ -2236,6 +2363,7 @@
B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */,
B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */,
B5220E1A1D130791009BC71E /* CoreStoreFetchedResultsController.swift in Sources */,
B5215CAC1FA4810300139E3A /* QueryChainBuilder.swift in Sources */,
B53FBA0F1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,
B52F744D1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */,
@@ -2243,6 +2371,8 @@
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */,
B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
B56923EB1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
B53B27621EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
B5215CA71FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
B5D33A041E96012400C880DE /* Relationship.swift in Sources */,
B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */,
B56923CC1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
@@ -2260,25 +2390,29 @@
B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */,
B5ECDC331CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */,
B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */,
B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */,
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */,
B5220E151D130663009BC71E /* CoreStore+Observing.swift in Sources */,
B549F6611E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */,
B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */,
B5CA2B151F81DBFF004B1936 /* DynamicKeyPath.swift in Sources */,
B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */,
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56924021EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
B56924021EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B5215CB11FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
B56923EF1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
B53FBA081CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */,
B5519A5C1CA2008C002BEF78 /* CSBaseDataTransaction.swift in Sources */,
B5DBE2D51C991B3E00B5CEFA /* CSDataStack.swift in Sources */,
B5831B731F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
B5AEFAB81C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
B598514B1C90289F00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */,
B5D339EA1E9493A500C880DE /* Entity.swift in Sources */,
B52DD1AA1BE1F93500949AFE /* ClauseTypes.swift in Sources */,
B52DD1AA1BE1F93500949AFE /* TypeErasedClauses.swift in Sources */,
B53FBA021CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */,
B51FE5AF1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
);
@@ -2323,6 +2457,7 @@
files = (
B56321A91BD65219006C9394 /* Progress+Convenience.swift in Sources */,
B5ECDBFC1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */,
B5CA2B0A1F7E5ACA004B1936 /* WhereClauseType.swift in Sources */,
B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */,
B56923F71EB828BF007C4DC9 /* CSDynamicSchema.swift in Sources */,
B56321801BD65216006C9394 /* CoreStoreError.swift in Sources */,
@@ -2334,13 +2469,14 @@
B5D339DA1E9489AB00C880DE /* CoreStoreObject.swift in Sources */,
B5ECDC021CA80CBA00C7F112 /* CSWhere.swift in Sources */,
B56923FC1EB82956007C4DC9 /* CSXcodeDataModelSchema.swift in Sources */,
B55514EC1EED8BF900BAB888 /* From+Querying.swift in Sources */,
B596BBBD1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */,
B5ECDC081CA8138100C7F112 /* CSOrderBy.swift in Sources */,
B5E1B59B1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */,
B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */,
B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModelSchema.swift in Sources */,
B52F74431E9B8724005F3DAC /* UnsafeDataModelSchema.swift in Sources */,
B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */,
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
@@ -2354,6 +2490,7 @@
B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */,
B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */,
B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */,
B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */,
B5D3F6471C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */,
B5D339F31E94AF5800C880DE /* CoreStoreStrings.swift in Sources */,
B5E1B5A01CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */,
@@ -2372,6 +2509,7 @@
B56321A81BD65219006C9394 /* NSManagedObject+Convenience.swift in Sources */,
B546F9751C9C553300D5AC55 /* SetupResult.swift in Sources */,
B56321981BD65216006C9394 /* Where.swift in Sources */,
B53CA9A41EF1EF1600E0F440 /* PartialObject.swift in Sources */,
B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */,
B5FE4DA91C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
B51260951E9B28F100402229 /* EntityIdentifier.swift in Sources */,
@@ -2392,6 +2530,7 @@
B501FDE51CA8D1F500BE22EF /* CSListMonitor.swift in Sources */,
B5E41EC21EA9BB37006240F0 /* DynamicSchema+Convenience.swift in Sources */,
B5ECDC141CA816E500C7F112 /* CSTweak.swift in Sources */,
B5A1DACA1F111BFA003CF369 /* KeyPath+Querying.swift in Sources */,
B56321AE1BD6521C006C9394 /* NotificationObserver.swift in Sources */,
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */,
B56923C61EB823B4007C4DC9 /* NSEntityDescription+Migration.swift in Sources */,
@@ -2420,6 +2559,7 @@
B563218E1BD65216006C9394 /* SaveResult.swift in Sources */,
B5E222261CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */,
B56321A21BD65216006C9394 /* ListObserver.swift in Sources */,
B5215CAB1FA4810300139E3A /* QueryChainBuilder.swift in Sources */,
B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */,
B52F744C1E9B8740005F3DAC /* CoreStoreSchema.swift in Sources */,
B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */,
@@ -2427,6 +2567,8 @@
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */,
B56923EA1EB827F5007C4DC9 /* InferredSchemaMappingProvider.swift in Sources */,
B53B27611EE3B92E00E9B352 /* CoreStoreManagedObject.swift in Sources */,
B5215CA61FA47DFD00139E3A /* FetchChainBuilder.swift in Sources */,
B5D33A031E96012400C880DE /* Relationship.swift in Sources */,
B559CD4C1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
B56923CB1EB82410007C4DC9 /* NSManagedObjectModel+Migration.swift in Sources */,
@@ -2444,27 +2586,31 @@
B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */,
B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */,
B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */,
B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */,
B53FBA211CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */,
B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */,
B549F6601E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
B559CD461CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
B56321A61BD65216006C9394 /* MigrationType.swift in Sources */,
B5CA2B141F81DBFE004B1936 /* DynamicKeyPath.swift in Sources */,
B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
B56924011EB82976007C4DC9 /* CSLegacyXcodeDataModelSchema.swift in Sources */,
B56924011EB82976007C4DC9 /* CSUnsafeDataModelSchema.swift in Sources */,
B5215CB01FA4812500139E3A /* SectionMonitorBuilder.swift in Sources */,
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
B56923EE1EB827F6007C4DC9 /* SchemaMappingProvider.swift in Sources */,
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */,
B53FBA071CAB300C00F0D40A /* CSMigrationType.swift in Sources */,
B56321841BD65216006C9394 /* DefaultLogger.swift in Sources */,
B5DBE2CF1C9914A900B5CEFA /* CSCoreStore.swift in Sources */,
B5831B721F34AC3400A9F647 /* AttributeProtocol.swift in Sources */,
B546F95F1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */,
B5ECDC0E1CA8161B00C7F112 /* CSGroupBy.swift in Sources */,
B5D339E91E9493A500C880DE /* Entity.swift in Sources */,
B56321A41BD65216006C9394 /* CoreStore+Migration.swift in Sources */,
B56321A01BD65216006C9394 /* ObjectObserver.swift in Sources */,
B56321951BD65216006C9394 /* ClauseTypes.swift in Sources */,
B56321951BD65216006C9394 /* TypeErasedClauses.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2498,14 +2644,21 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -2539,6 +2692,8 @@
PRODUCT_NAME = CoreStore;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
@@ -2556,14 +2711,21 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -2590,6 +2752,8 @@
PRODUCT_NAME = CoreStore;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 9.0;
VALIDATE_PRODUCT = YES;
@@ -2613,7 +2777,8 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -2631,7 +2796,8 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -2651,7 +2817,8 @@
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -2666,7 +2833,8 @@
PRODUCT_NAME = CoreStoreTests;
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -2686,7 +2854,8 @@
SDKROOT = appletvos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 3;
};
name = Debug;
@@ -2707,7 +2876,8 @@
SDKROOT = appletvos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 3;
};
name = Release;
@@ -2725,7 +2895,8 @@
SDKROOT = appletvos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 3;
};
name = Debug;
@@ -2743,7 +2914,8 @@
PRODUCT_NAME = CoreStoreTests;
SDKROOT = appletvos;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 3;
};
name = Release;
@@ -2767,7 +2939,8 @@
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -2791,7 +2964,8 @@
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -2811,7 +2985,8 @@
SDKROOT = macosx;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -2831,7 +3006,8 @@
PRODUCT_NAME = CoreStoreTests;
SDKROOT = macosx;
SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -2852,7 +3028,8 @@
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 4;
};
name = Debug;
@@ -2875,7 +3052,8 @@
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = 4;
};
name = Release;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -55,6 +56,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -74,6 +75,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -55,6 +56,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -36,6 +37,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -265,12 +265,12 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0800;
LastUpgradeCheck = 0900;
ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = {
B54AAD481AF4D26E00848AE0 = {
CreatedOnToolsVersion = 6.3;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
};
};
@@ -371,14 +371,20 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
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_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -407,6 +413,8 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -418,14 +426,20 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
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_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -445,6 +459,8 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -458,7 +474,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -472,7 +489,8 @@
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
};
name = Release;
};

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -45,6 +46,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -8,7 +8,6 @@
import UIKit
import CoreStore
// MARK: - AppDelegate

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12113" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12078"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
@@ -459,8 +459,8 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
<rect key="frame" x="20" y="69.5" width="552" height="36.5"/>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
<rect key="frame" x="16" y="89.5" width="343" height="50"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
@@ -511,8 +511,8 @@
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
<rect key="frame" x="20" y="49" width="552" height="20.5"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
<rect key="frame" x="16" y="69" width="343" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@@ -797,8 +797,8 @@
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
<rect key="frame" x="0.0" y="0.0" width="375" height="536"/>
<mapView verifyAmbiguity="ignoreSizes" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
<rect key="frame" x="0.0" y="0.0" width="375" height="558"/>
<connections>
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
</connections>
@@ -806,7 +806,7 @@
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="RZg-hi-T8O" firstAttribute="top" secondItem="V2U-0R-Ts0" secondAttribute="bottom" id="GcS-Jz-Wcm"/>
<constraint firstItem="RZg-hi-T8O" firstAttribute="top" secondItem="V2U-0R-Ts0" secondAttribute="bottom" id="N9r-9J-68d"/>
<constraint firstItem="V2U-0R-Ts0" firstAttribute="top" secondItem="k4s-iL-Krh" secondAttribute="top" id="S5Z-Da-V6J"/>
<constraint firstAttribute="trailing" secondItem="V2U-0R-Ts0" secondAttribute="trailing" id="YPc-RK-5ib"/>
<constraint firstItem="V2U-0R-Ts0" firstAttribute="leading" secondItem="k4s-iL-Krh" secondAttribute="leading" id="hk5-Rz-FyU"/>
@@ -820,7 +820,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="YnG-TD-zxQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3694" y="2020"/>
<point key="canvasLocation" x="3693.5" y="2019.5"/>
</scene>
<!--Logger-->
<scene sceneID="n7W-0g-bbY">
@@ -927,7 +927,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="YVj-dA-fyV">
<rect key="frame" x="20" y="26" width="560" height="29"/>
<rect key="frame" x="20" y="26" width="335" height="29"/>
<segments>
<segment title="Fetch"/>
<segment title="Query"/>

View File

@@ -1,36 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10169.1" systemVersion="15D21" minimumToolsVersion="Automatic">
<entity name="Palette" representedClassName="CoreStoreDemo.Palette">
<attribute name="brightness" optional="YES" attributeType="Float" defaultValueString="0.0" syncable="YES"/>
<attribute name="colorName" optional="YES" transient="YES" attributeType="String" syncable="YES"/>
<attribute name="hue" optional="YES" attributeType="Integer 32" defaultValueString="0.0" syncable="YES"/>
<attribute name="saturation" optional="YES" attributeType="Float" defaultValueString="0.0" syncable="YES"/>
<userInfo/>
</entity>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16F73" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="Place" representedClassName="CoreStoreDemo.Place" syncable="YES">
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="subtitle" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
</entity>
<entity name="TimeZone" representedClassName="CoreStoreDemo.TimeZone" syncable="YES">
<attribute name="abbreviation" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" syncable="YES"/>
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" syncable="YES"/>
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
</entity>
<configuration name="FetchingAndQueryingDemo">
<memberEntity name="TimeZone"/>
</configuration>
<configuration name="ObservingDemo">
<memberEntity name="Palette"/>
</configuration>
<configuration name="TransactionsDemo">
<memberEntity name="Place"/>
</configuration>
<elements>
<element name="Palette" positionX="261" positionY="189" width="128" height="105"/>
<element name="Place" positionX="261" positionY="225" width="128" height="105"/>
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
</elements>

View File

@@ -165,8 +165,8 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From<TimeZone>(),
OrderBy(.ascending(#keyPath(TimeZone.name)))
From<TimeZone>()
.orderBy(.ascending(\.name))
)!
}
),
@@ -175,9 +175,13 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From<TimeZone>(),
Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Asia"),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"Asia"
)
.orderBy(.ascending(\.secondsFromGMT))
)!
}
),
@@ -186,10 +190,15 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From<TimeZone>(),
Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America")
|| Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Europe"),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@ OR %K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"America",
#keyPath(TimeZone.name),
"Europe"
)
.orderBy(.ascending(\.secondsFromGMT))
)!
}
),
@@ -198,9 +207,13 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From<TimeZone>(),
!Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America"),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"America"
)
.orderBy(.ascending(\.secondsFromGMT))
)!
}
),
@@ -209,23 +222,23 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From<TimeZone>(),
Where("hasDaylightSavingTime", isEqualTo: true),
OrderBy(.ascending(#keyPath(TimeZone.name)))
From<TimeZone>()
.where(\.hasDaylightSavingTime == true)
.orderBy(.ascending(\.name))
)!
}
)
]
private let queryingItems = [
private let queryingItems: [(title: String, query: () -> Any)] = [
(
title: "Number of Time Zones",
query: { () -> Any in
return Static.timeZonesStack.queryValue(
From<TimeZone>(),
Select<NSNumber>(.count(#keyPath(TimeZone.name)))
)!
From<TimeZone>()
.select(NSNumber.self, .count(\.name))
)! as Any
}
),
(
@@ -233,10 +246,10 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
query: { () -> Any in
return Static.timeZonesStack.queryValue(
From<TimeZone>(),
Select<String>(#keyPath(TimeZone.abbreviation)),
Where("%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
)!
From<TimeZone>()
.select(String.self, .attribute(\.abbreviation))
.where(format: "%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
)! as Any
}
),
(
@@ -244,9 +257,13 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
query: { () -> Any in
return Static.timeZonesStack.queryAttributes(
From<TimeZone>(),
Select<NSDictionary>(#keyPath(TimeZone.name), #keyPath(TimeZone.abbreviation)),
OrderBy(.ascending(#keyPath(TimeZone.name)))
From<TimeZone>()
.select(
NSDictionary.self,
.attribute(\.name),
.attribute(\.abbreviation)
)
.orderBy(.ascending(\.name))
)!
}
),
@@ -255,10 +272,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
query: { () -> Any in
return Static.timeZonesStack.queryAttributes(
From<TimeZone>(),
Select<NSDictionary>(.count(#keyPath(TimeZone.abbreviation)), #keyPath(TimeZone.abbreviation)),
GroupBy(#keyPath(TimeZone.abbreviation)),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)), .ascending(#keyPath(TimeZone.name)))
From<TimeZone>()
.select(
NSDictionary.self,
.count(\.abbreviation),
.attribute(\.abbreviation)
)
.groupBy(\.abbreviation)
.orderBy(
.ascending(\.secondsFromGMT),
.ascending(\.name)
)
)!
}
),
@@ -267,13 +291,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
query: { () -> Any in
return Static.timeZonesStack.queryAttributes(
From<TimeZone>(),
Select<NSDictionary>(
.count(#keyPath(TimeZone.hasDaylightSavingTime), as: "numberOfCountries"),
#keyPath(TimeZone.hasDaylightSavingTime)
),
GroupBy(#keyPath(TimeZone.hasDaylightSavingTime)),
OrderBy(.descending(#keyPath(TimeZone.hasDaylightSavingTime)))
From<TimeZone>()
.select(
NSDictionary.self,
.count(\.hasDaylightSavingTime, as: "numberOfCountries"),
.attribute(\.hasDaylightSavingTime)
)
.groupBy(\.hasDaylightSavingTime)
.orderBy(
.descending(\.hasDaylightSavingTime),
.ascending(\.name)
)
)!
}
)

View File

@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.1</string>
<string>4.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>4</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>

View File

@@ -10,7 +10,7 @@ import UIKit
import CoreStore
private struct Static {
struct ColorsDemo {
enum Filter: String {
@@ -28,13 +28,13 @@ private struct Static {
}
}
func whereClause() -> Where {
func whereClause() -> Where<Palette> {
switch self {
case .all: return Where(true)
case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9)
case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4)
case .all: return .init()
case .light: return (\Palette.brightness >= 0.9)
case .dark: return (\Palette.brightness <= 0.4)
}
}
}
@@ -45,25 +45,38 @@ private struct Static {
self.palettes.refetch(
self.filter.whereClause(),
OrderBy(.ascending(#keyPath(Palette.hue)))
OrderBy<Palette>(.ascending(\.hue))
)
}
}
static let stack: DataStack = {
return DataStack(
CoreStoreSchema(
modelVersion: "ColorsDemo",
entities: [
Entity<Palette>("Palette"),
],
versionLock: [
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
]
)
)
}()
static let palettes: ListMonitor<Palette> = {
try! CoreStore.addStorageAndWait(
try! ColorsDemo.stack.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
configuration: "ObservingDemo",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
return CoreStore.monitorSectionedList(
From<Palette>(),
SectionBy(#keyPath(Palette.colorName)),
OrderBy(.ascending(#keyPath(Palette.hue)))
return ColorsDemo.stack.monitorSectionedList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
)
}()
}
@@ -77,7 +90,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
deinit {
Static.palettes.removeObserver(self)
ColorsDemo.palettes.removeObserver(self)
}
@@ -98,7 +111,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
]
let filterBarButton = UIBarButtonItem(
title: Static.filter.rawValue,
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
@@ -113,9 +126,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
]
self.filterBarButton = filterBarButton
Static.palettes.addObserver(self)
ColorsDemo.palettes.addObserver(self)
self.setTable(enabled: !Static.palettes.isPendingRefetch)
self.setTable(enabled: !ColorsDemo.palettes.isPendingRefetch)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
@@ -137,19 +150,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
override func numberOfSections(in tableView: UITableView) -> Int {
return Static.palettes.numberOfSections()
return ColorsDemo.palettes.numberOfSections()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Static.palettes.numberOfObjectsInSection(section)
return ColorsDemo.palettes.numberOfObjectsInSection(section)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
let palette = Static.palettes[indexPath]
let palette = ColorsDemo.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
@@ -165,7 +178,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: Static.palettes[indexPath]
sender: ColorsDemo.palettes[indexPath]
)
}
@@ -174,8 +187,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
switch editingStyle {
case .delete:
let palette = Static.palettes[indexPath]
CoreStore.perform(
let palette = ColorsDemo.palettes[indexPath]
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.delete(palette)
@@ -190,7 +203,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return Static.palettes.sectionInfoAtIndex(section).name
return ColorsDemo.palettes.sectionInfoAtIndex(section).name
}
@@ -213,7 +226,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
self.filterBarButton?.title = Static.filter.rawValue
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.tableView.reloadData()
self.setTable(enabled: true)
}
@@ -235,7 +248,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell {
let palette = Static.palettes[indexPath]
let palette = ColorsDemo.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
}
@@ -268,7 +281,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
CoreStore.perform(
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.deleteAll(From<Palette>())
@@ -279,16 +292,16 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
Static.filter = Static.filter.next()
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
CoreStore.perform(
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues()
palette.setInitialValues(in: transaction)
},
completion: { _ in }
)

View File

@@ -29,7 +29,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = newValue {
self.monitor = CoreStore.monitorObject(palette)
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
else {
@@ -50,22 +50,22 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
required init?(coder aDecoder: NSCoder) {
if let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue)))) {
if let palette = ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue))) {
self.monitor = CoreStore.monitorObject(palette)
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
else {
_ = try? CoreStore.perform(
_ = try? ColorsDemo.stack.perform(
synchronous: { (transaction) in
let palette = transaction.create(Into(Palette.self))
palette.setInitialValues()
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
}
)
let palette = CoreStore.fetchOne(From<Palette>(), OrderBy(.ascending(#keyPath(Palette.hue))))!
self.monitor = CoreStore.monitorObject(palette)
let palette = ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue)))!
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
super.init(coder: aDecoder)
@@ -85,7 +85,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
// MARK: ObjectObserver
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPath>) {
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPathString>) {
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
}
@@ -121,12 +121,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
let hue = self.hueSlider?.value ?? 0
CoreStore.perform(
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.hue = Int32(hue)
palette.hue .= Int(hue)
}
},
completion: { _ in }
@@ -136,12 +136,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
let saturation = self.saturationSlider?.value ?? 0
CoreStore.perform(
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.saturation = saturation
palette.saturation .= saturation
}
},
completion: { _ in }
@@ -151,12 +151,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
let brightness = self.brightnessSlider?.value ?? 0
CoreStore.perform(
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.brightness = brightness
palette.brightness .= brightness
}
},
completion: { _ in }
@@ -165,7 +165,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
CoreStore.perform(
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
transaction.delete(self?.monitor?.object)
@@ -176,7 +176,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
self.colorNameLabel?.text = palette.colorName
self.colorNameLabel?.text = palette.colorName.value
let color = palette.color
self.colorNameLabel?.textColor = color
@@ -184,17 +184,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
self.hsbLabel?.text = palette.colorText
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.hue)) == true {
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.hue }) == true {
self.hueSlider?.value = Float(palette.hue)
self.hueSlider?.value = Float(palette.hue.value)
}
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.saturation)) == true {
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.saturation }) == true {
self.saturationSlider?.value = palette.saturation
self.saturationSlider?.value = palette.saturation.value
}
if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.brightness)) == true {
if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.brightness }) == true {
self.brightnessSlider?.value = palette.brightness
self.brightnessSlider?.value = palette.brightness.value
}
}
}

View File

@@ -14,64 +14,65 @@ import CoreStore
// MARK: - Palette
class Palette: NSManagedObject {
@NSManaged var hue: Int32
@NSManaged var saturation: Float
@NSManaged var brightness: Float
final class Palette: CoreStoreObject {
@objc dynamic var colorName: String {
let hue = Value.Required<Int>("hue", initial: 0)
let saturation = Value.Required<Float>("saturation", initial: 0)
let brightness = Value.Required<Float>("brightness", initial: 0)
let colorName = Value.Optional<String>(
"colorName",
isTransient: true,
customGetter: Palette.getColorName
)
private static func getColorName(_ partialObject: PartialObject<Palette>) -> String? {
get {
if let colorName = partialObject.primitiveValue(for: { $0.colorName }) {
let KVCKey = #keyPath(Palette.colorName)
if let colorName = self.getValue(forKvcKey: KVCKey) as? String {
return colorName
}
let colorName: String
switch self.hue % 360 {
case 0 ..< 20: colorName = "Lower Reds"
case 20 ..< 57: colorName = "Oranges and Browns"
case 57 ..< 90: colorName = "Yellow-Greens"
case 90 ..< 159: colorName = "Greens"
case 159 ..< 197: colorName = "Blue-Greens"
case 197 ..< 241: colorName = "Blues"
case 241 ..< 297: colorName = "Violets"
case 297 ..< 331: colorName = "Magentas"
default: colorName = "Upper Reds"
}
self.setPrimitiveValue(colorName, forKey: KVCKey)
return colorName
}
set {
let colorName: String
switch partialObject.value(for: { $0.hue }) % 360 {
self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName))
case 0 ..< 20: colorName = "Lower Reds"
case 20 ..< 57: colorName = "Oranges and Browns"
case 57 ..< 90: colorName = "Yellow-Greens"
case 90 ..< 159: colorName = "Greens"
case 159 ..< 197: colorName = "Blue-Greens"
case 197 ..< 241: colorName = "Blues"
case 241 ..< 297: colorName = "Violets"
case 297 ..< 331: colorName = "Magentas"
default: colorName = "Upper Reds"
}
partialObject.setPrimitiveValue(colorName, for: { $0.colorName })
return colorName
}
}
extension Palette {
var color: UIColor {
return UIColor(
hue: CGFloat(self.hue) / 360.0,
saturation: CGFloat(self.saturation),
brightness: CGFloat(self.brightness),
hue: CGFloat(self.hue.value) / 360.0,
saturation: CGFloat(self.saturation.value),
brightness: CGFloat(self.brightness.value),
alpha: 1.0
)
}
var colorText: String {
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%"
}
func setInitialValues() {
func setInitialValues(in transaction: BaseDataTransaction) {
self.hue = Int32(arc4random_uniform(360))
self.saturation = 1.0
self.brightness = Float(arc4random_uniform(70) + 30) / 100.0
self.hue .= Int(arc4random_uniform(360))
self.saturation .= Float(1.0)
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
}
}

View File

@@ -99,8 +99,8 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
case 0?:
let request = NSFetchRequest<NSFetchRequestResult>()
Where(true).applyToFetchRequest(request)
Where(false).applyToFetchRequest(request)
Where<NSManagedObject>(true).applyToFetchRequest(request)
Where<NSManagedObject>(false).applyToFetchRequest(request)
case 1?:
_ = try? dataStack.addStorageAndWait(
@@ -113,7 +113,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
case 2?:
DispatchQueue.global(qos: .background).async {
_ = self.dataStack.fetchOne(From<Palette>())
_ = self.dataStack.fetchOne(From<Place>())
}
default:

View File

@@ -46,7 +46,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
self.present(alert, animated: true, completion: nil)
let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) {
let modelMetadata = withExtendedLifetime(DataStack(xcodeModelName: "MigrationDemo")) {
(dataStack: DataStack) -> ModelMetadata in
let models = self.models
@@ -91,6 +91,11 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
}
}
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
self.listMonitorDidChange(monitor)
}
// MARK: UITableViewDataSource
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
@@ -104,7 +109,7 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
cell.dnaLabel?.text = "DNA: \(dna)"
cell.mutateButtonHandler = { [weak self] _ -> Void in
cell.mutateButtonHandler = { [weak self] () -> Void in
guard let `self` = self,
let dataStack = self.dataStack,
@@ -148,7 +153,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
label: "Model V1",
entityType: OrganismV1.self,
schemaHistory: SchemaHistory(
modelName: "MigrationDemo",
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
),
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
)
),
@@ -156,7 +164,13 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
label: "Model V2",
entityType: OrganismV2.self,
schemaHistory: SchemaHistory(
modelName: "MigrationDemo",
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
),
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
@@ -167,7 +181,10 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
label: "Model V3",
entityType: OrganismV3.self,
schemaHistory: SchemaHistory(
modelName: "MigrationDemo",
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
),
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
)
@@ -270,8 +287,8 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
self.set(dataStack: dataStack, model: model, scrollToSelection: true)
let count = dataStack.queryValue(
From(model.entityType),
Select<Int>(.count(#keyPath(OrganismV1.dna))))!
From<NSManagedObject>(model.entityType)
.select(Int.self, .count(#keyPath(OrganismV1.dna))))!
if count > 0 {
self.setEnabled(true)
@@ -344,14 +361,18 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
self.segmentedControl?.selectedSegmentIndex = self.models
.index(
where: { (_, _, schemaHistory) -> Bool in
where: { (arg) -> Bool in
schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
let (_, _, schemaHistory) = arg
return schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
}
)!
self._dataStack = dataStack
let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna")))
let listMonitor = dataStack.monitorList(
From(model.entityType),
OrderBy<NSManagedObject>(.descending(#keyPath(OrganismV1.dna)))
)
listMonitor.addObserver(self)
self._listMonitor = listMonitor

View File

@@ -17,7 +17,7 @@ private struct Static {
static let facebookStack: DataStack = {
let dataStack = DataStack(modelName: "StackSetupDemo")
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_FB_Male.sqlite",
@@ -55,7 +55,7 @@ private struct Static {
static let twitterStack: DataStack = {
let dataStack = DataStack(modelName: "StackSetupDemo")
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_TW_Male.sqlite",

View File

@@ -131,7 +131,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
// none
}
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPath>) {
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPathString>) {
if let mapView = self.mapView {

View File

@@ -40,7 +40,7 @@ class BaseTestCase: XCTestCase {
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {

View File

@@ -2,8 +2,25 @@
// BaseTestDataTestCase.swift
// CoreStore
//
// Created by John Rommel Estropia on 2016/06/11.
// Copyright © 2016 John Rommel Estropia. All rights reserved.
// 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

View File

@@ -163,7 +163,7 @@
- (void)test_ThatDataStacks_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc]
initWithModelName:@"Model"
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil];
XCTAssertNotNil(dataStack);
@@ -201,7 +201,7 @@
[CSCoreStore
setDefaultStack:[[CSDataStack alloc]
initWithModelName:@"Model"
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]];
[CSCoreStore
@@ -253,37 +253,5 @@
}
[self waitForExpectationsWithTimeout:10 handler:nil];
}
#if TARGET_OS_IOS || TARGET_OS_WATCHOS || TARGET_OS_TV
- (void)test_ThatDataStacks_CanCreateCustomFetchedResultsControllers {
[CSCoreStore
setDefaultStack:[[CSDataStack alloc]
initWithModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]];
[CSCoreStore
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
NSFetchedResultsController *controller =
[[CSCoreStore defaultStack]
createFetchedResultsControllerFrom:CSFromClass([TestEntity1 class])
sectionBy:[CSSectionBy keyPath:CSKeyPath(TestEntity1, testString)]
fetchClauses:@[CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100),
CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil),
CSTweakRequest(^(NSFetchRequest *fetchRequest) { fetchRequest.fetchLimit = 10; })]];
XCTAssertNotNil(controller);
XCTAssertEqualObjects(controller.fetchRequest.entity.managedObjectClassName, [[TestEntity1 class] description]);
XCTAssertEqualObjects(controller.sectionNameKeyPath, CSKeyPath(TestEntity1, testString));
XCTAssertEqualObjects(controller.fetchRequest.predicate,
CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100).predicate);
XCTAssertEqualObjects(controller.fetchRequest.sortDescriptors,
CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil).sortDescriptors);
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10);
}
#endif
@end

View File

@@ -40,8 +40,8 @@ class ConvenienceTests: BaseTestCase {
let controller = stack.createFetchedResultsController(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testString)),
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
OrderBy(.ascending(#keyPath(TestEntity1.testString))),
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))),
Tweak { $0.fetchLimit = 10 }
)
XCTAssertEqual(controller.managedObjectContext, stack.mainContext)
@@ -49,11 +49,11 @@ class ConvenienceTests: BaseTestCase {
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
XCTAssertEqual(
controller.fetchRequest.sortDescriptors!,
OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
)
XCTAssertEqual(
controller.fetchRequest.predicate,
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
)
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
}
@@ -69,8 +69,8 @@ class ConvenienceTests: BaseTestCase {
let controller = transaction.createFetchedResultsController(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testString)),
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
OrderBy(.ascending(#keyPath(TestEntity1.testString))),
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))),
Tweak { $0.fetchLimit = 10 }
)
XCTAssertEqual(controller.managedObjectContext, transaction.context)
@@ -78,11 +78,11 @@ class ConvenienceTests: BaseTestCase {
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
XCTAssertEqual(
controller.fetchRequest.sortDescriptors!,
OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
)
XCTAssertEqual(
controller.fetchRequest.predicate,
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
Where<TestEntity1>("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
)
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
}

View File

@@ -28,32 +28,83 @@ import XCTest
@testable
import CoreStore
#if os(OSX)
typealias Color = NSColor
#else
typealias Color = UIColor
#endif
class Animal: CoreStoreObject {
let species = Value.Required<String>("species", default: "Swift")
let species = Value.Required<String>("species", initial: "Swift")
let master = Relationship.ToOne<Person>("master")
let color = Transformable.Optional<UIColor>("color")
let color = Transformable.Optional<Color>("color")
}
class Dog: Animal {
let nickname = Value.Optional<String>("nickname")
let age = Value.Required<Int>("age", default: 1)
let age = Value.Required<Int>("age", initial: 1)
let friends = Relationship.ToManyOrdered<Dog>("friends")
let friendedBy = Relationship.ToManyUnordered<Dog>("friendedBy", inverse: { $0.friends })
}
class Person: CoreStoreObject {
let title = Value.Required<String>("title", default: "Mr.")
let title = Value.Required<String>(
"title",
initial: "Mr.",
customSetter: Person.setTitle
)
let name = Value.Required<String>(
"name",
customGetter: { (`self`, getValue) in
return "\(self.title.value) \(getValue())"
}
initial: "",
customSetter: Person.setName
)
let displayName = Value.Optional<String>(
"displayName",
isTransient: true,
customGetter: Person.getDisplayName(_:),
affectedByKeyPaths: Person.keyPathsAffectingDisplayName()
)
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
private static func setTitle(_ partialObject: PartialObject<Person>, _ newValue: String) {
partialObject.setPrimitiveValue(newValue, for: { $0.title })
partialObject.setPrimitiveValue(nil, for: { $0.displayName })
}
private static func setName(_ partialObject: PartialObject<Person>, _ newValue: String) {
partialObject.setPrimitiveValue(newValue, for: { $0.name })
partialObject.setPrimitiveValue(nil, for: { $0.displayName })
}
static func getDisplayName(_ partialObject: PartialObject<Person>) -> String? {
if let displayName = partialObject.primitiveValue(for: { $0.displayName }) {
return displayName
}
let title = partialObject.value(for: { $0.title })
let name = partialObject.value(for: { $0.name })
let displayName = "\(title) \(name)"
partialObject.setPrimitiveValue(displayName, for: { $0.displayName })
return displayName
}
static func keyPathsAffectingDisplayName() -> Set<String> {
return [
String(keyPath: \Person.title),
String(keyPath: \Person.name)
]
}
}
@@ -61,7 +112,8 @@ class Person: CoreStoreObject {
class DynamicModelTests: BaseTestDataTestCase {
func testDynamicModels_CanBeDeclaredCorrectly() {
@objc
dynamic func test_ThatDynamicModels_CanBeDeclaredCorrectly() {
let dataStack = DataStack(
CoreStoreSchema(
@@ -80,13 +132,13 @@ class DynamicModelTests: BaseTestDataTestCase {
)
self.prepareStack(dataStack, configurations: [nil]) { (stack) in
let k1 = Animal.keyPath({ $0.species })
let k1 = String(keyPath: \Animal.species)
XCTAssertEqual(k1, "species")
let k2 = Dog.keyPath({ $0.species })
let k2 = String(keyPath: \Dog.species)
XCTAssertEqual(k2, "species")
let k3 = Dog.keyPath({ $0.nickname })
let k3 = String(keyPath: \Dog.nickname)
XCTAssertEqual(k3, "nickname")
let updateDone = self.expectation(description: "update-done")
@@ -102,7 +154,7 @@ class DynamicModelTests: BaseTestDataTestCase {
XCTAssertEqual(animal.species.value, "Sparrow")
animal.color .= .yellow
XCTAssertEqual(animal.color.value, UIColor.yellow)
XCTAssertEqual(animal.color.value, Color.yellow)
let dog = transaction.create(Into<Dog>())
XCTAssertEqual(dog.species.value, "Swift")
@@ -118,11 +170,25 @@ class DynamicModelTests: BaseTestDataTestCase {
let person = transaction.create(Into<Person>())
XCTAssertTrue(person.pets.value.isEmpty)
XCTAssertEqual(
type(of: person.rawObject!).keyPathsForValuesAffectingValue(forKey: "displayName"),
["title", "name"]
)
person.name .= "Joe"
XCTAssertEqual(person.rawObject!.value(forKey: "name") as! String?, "Joe")
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "Mr. Joe")
person.rawObject!.setValue("AAAA", forKey: "displayName")
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "AAAA")
person.name .= "John"
XCTAssertEqual(person.name.value, "Mr. John") // Custom getter
XCTAssertEqual(person.name.value, "John")
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
person.title .= "Sir"
XCTAssertEqual(person.name.value, "Sir John")
XCTAssertEqual(person.displayName.value, "Sir John")
person.pets.value.insert(dog)
XCTAssertEqual(person.pets.count, 1)
@@ -131,7 +197,7 @@ class DynamicModelTests: BaseTestDataTestCase {
XCTAssertEqual(dog.master.value, person)
XCTAssertEqual(dog.master.value?.pets.value.first, dog)
},
success: {
success: { _ in
updateDone.fulfill()
},
@@ -143,17 +209,17 @@ class DynamicModelTests: BaseTestDataTestCase {
stack.perform(
asynchronous: { (transaction) in
let p1 = Animal.where({ $0.species == "Sparrow" })
let p1 = Where<Animal>({ $0.species == "Sparrow" })
XCTAssertEqual(p1.predicate, NSPredicate(format: "%K == %@", "species", "Sparrow"))
let bird = transaction.fetchOne(From<Animal>(), p1)
XCTAssertNotNil(bird)
XCTAssertEqual(bird!.species.value, "Sparrow")
let p2 = Dog.where({ $0.nickname == "Spot" })
let p2 = Where<Dog>({ $0.nickname == "Spot" })
XCTAssertEqual(p2.predicate, NSPredicate(format: "%K == %@", "nickname", "Spot"))
let dog = transaction.fetchOne(From<Dog>(), p2)
let dog = transaction.fetchOne(From<Dog>().where(\.nickname == "Spot"))
XCTAssertNotNil(dog)
XCTAssertEqual(dog!.nickname.value, "Spot")
XCTAssertEqual(dog!.species.value, "Dog")
@@ -162,13 +228,42 @@ class DynamicModelTests: BaseTestDataTestCase {
XCTAssertNotNil(person)
XCTAssertEqual(person!.pets.value.first, dog)
let p3 = Dog.where({ $0.age == 10 })
let p3 = Where<Dog>({ $0.age == 10 })
XCTAssertEqual(p3.predicate, NSPredicate(format: "%K == %d", "age", 10))
_ = transaction.fetchAll(
From<Dog>()
.where(\Animal.species == "Dog" && \.age == 10)
)
_ = transaction.fetchAll(
From<Dog>()
.where(\.age == 10 && \Animal.species == "Dog")
.orderBy(.ascending({ $0.species }))
)
_ = transaction.fetchAll(
From<Dog>(),
Where<Dog>({ $0.age > 10 && $0.age <= 15 })
)
_ = transaction.fetchAll(
From<Dog>(),
Where<Dog>({ $0.species == "Dog" && $0.age == 10 })
)
_ = transaction.fetchAll(
From<Dog>(),
Where<Dog>({ $0.age == 10 && $0.species == "Dog" })
)
_ = transaction.fetchAll(
From<Dog>(),
Where<Dog>({ $0.age > 10 && $0.age <= 15 })
)
_ = transaction.fetchAll(
From<Dog>(),
(\Dog.age > 10 && \Dog.age <= 15)
)
},
success: {
success: { _ in
fetchDone.fulfill()
withExtendedLifetime(stack, {})
},
failure: { _ in
@@ -179,6 +274,13 @@ class DynamicModelTests: BaseTestDataTestCase {
}
}
@objc
dynamic func test_ThatDynamicModelKeyPaths_CanBeCreated() {
XCTAssertEqual(String(keyPath: \Animal.species), "species")
XCTAssertEqual(String(keyPath: \Dog.species), "species")
}
@nonobjc
func prepareStack(_ dataStack: DataStack, configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> Void) {

View File

@@ -86,8 +86,10 @@ final class ErrorTests: XCTestCase {
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
let schemaHistory = SchemaHistory(
modelName: "Model",
bundle: Bundle(for: type(of: self))
XcodeDataModelSchema.from(
modelName: "Model",
bundle: Bundle(for: type(of: self))
)
)
let version = "1.0.0"

File diff suppressed because it is too large Load Diff

View File

@@ -38,14 +38,14 @@ final class GroupByTests: BaseTestCase {
do {
let groupBy = GroupBy()
let groupBy = GroupBy<NSManagedObject>()
XCTAssertEqual(groupBy, GroupBy([] as [String]))
XCTAssertNotEqual(groupBy, GroupBy("key"))
XCTAssertTrue(groupBy.keyPaths.isEmpty)
}
do {
let groupBy = GroupBy("key1")
let groupBy = GroupBy<NSManagedObject>("key1")
XCTAssertEqual(groupBy, GroupBy("key1"))
XCTAssertEqual(groupBy, GroupBy(["key1"]))
XCTAssertNotEqual(groupBy, GroupBy("key2"))
@@ -53,7 +53,7 @@ final class GroupByTests: BaseTestCase {
}
do {
let groupBy = GroupBy("key1", "key2")
let groupBy = GroupBy<NSManagedObject>("key1", "key2")
XCTAssertEqual(groupBy, GroupBy("key1", "key2"))
XCTAssertEqual(groupBy, GroupBy(["key1", "key2"]))
XCTAssertNotEqual(groupBy, GroupBy("key2", "key1"))
@@ -66,7 +66,7 @@ final class GroupByTests: BaseTestCase {
self.prepareStack { (dataStack) in
let groupBy = GroupBy(#keyPath(TestEntity1.testString))
let groupBy = GroupBy<NSManagedObject>(#keyPath(TestEntity1.testString))
let request = CoreStoreFetchRequest()
_ = From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext)

View File

@@ -36,33 +36,33 @@ class ImportTests: BaseTestDataTestCase {
@objc
dynamic func test_ThatAttributeProtocols_BehaveCorrectly() {
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: true))?.boolValue, true)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT))
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: true))?.boolValue, true)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT))
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue)
XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue)
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: true)))
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int16.max)))
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int32.max)))
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int64.max)))
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: MAXFLOAT)))
XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Double(MAXFLOAT))))
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: true)))
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max)))
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max)))
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max)))
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT)))
XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT))))
XCTAssertEqual(true.cs_toQueryableNativeType(), NSNumber(value: true))
XCTAssertEqual(Int16.max.cs_toQueryableNativeType(), NSNumber(value: Int16.max))
@@ -444,7 +444,7 @@ class ImportTests: BaseTestDataTestCase {
XCTAssertNil(object)
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
XCTAssertNotNil(existingObjects)
XCTAssertEqual(existingObjects?.count, 1)
@@ -565,7 +565,9 @@ class ImportTests: BaseTestDataTestCase {
XCTAssertEqual(objects.count, 2)
zip(objects, sourceArray)
.forEach { object, dictionary in
.forEach {
let (object, dictionary) = $0
XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber)
XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber)
XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber)
@@ -618,7 +620,7 @@ class ImportTests: BaseTestDataTestCase {
errorExpectation.fulfill()
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 6)
let object = transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
let object = transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
XCTAssertNotNil(object)
XCTAssertEqual(object?.testEntityID, NSNumber(value: 106))
XCTAssertNil(object?.testBoolean)
@@ -657,7 +659,7 @@ class ImportTests: BaseTestDataTestCase {
errorExpectation.fulfill()
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 6)
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
XCTAssertNotNil(existingObjects)
XCTAssertEqual(existingObjects?.count, 1)
@@ -743,7 +745,7 @@ class ImportTests: BaseTestDataTestCase {
XCTAssertEqual(object?.testData, ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-07T00:00:00Z")!)
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
XCTAssertNotNil(existingObjects)
XCTAssertEqual(existingObjects?.count, 1)
@@ -864,8 +866,8 @@ class ImportTests: BaseTestDataTestCase {
errorExpectation.fulfill()
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)))
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 107)))
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)))
XCTAssertNil(transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 107)))
}
transaction.unsafeContext().reset()
self.checkExpectationsImmediately()
@@ -908,7 +910,7 @@ class ImportTests: BaseTestDataTestCase {
errorExpectation.fulfill()
let object = transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
let object = transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))
XCTAssertNotNil(object)
XCTAssertEqual(object?.testEntityID, NSNumber(value: 106))
XCTAssertNil(object?.testBoolean)
@@ -951,7 +953,7 @@ class ImportTests: BaseTestDataTestCase {
errorExpectation.fulfill()
XCTAssertEqual(transaction.fetchCount(From<TestEntity1>()), 5)
let object = transaction.fetchOne(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
let object = transaction.fetchOne(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
XCTAssertNotNil(object)
XCTAssertEqual(object?.testEntityID, NSNumber(value: 105))
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
@@ -961,7 +963,7 @@ class ImportTests: BaseTestDataTestCase {
XCTAssertEqual(object?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!)
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
XCTAssertNotNil(existingObjects)
XCTAssertEqual(existingObjects?.count, 1)
@@ -1030,7 +1032,7 @@ class ImportTests: BaseTestDataTestCase {
XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data)
XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date)
}
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
let existingObjects = transaction.fetchAll(From<TestEntity1>(), Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 105))
XCTAssertNotNil(existingObjects)
XCTAssertEqual(existingObjects?.count, 1)

View File

@@ -43,7 +43,7 @@ class ListObserverTests: BaseTestDataTestCase {
let monitor = stack.monitorSectionedList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
@@ -54,7 +54,7 @@ class ListObserverTests: BaseTestDataTestCase {
var events = 0
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -68,7 +68,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
let didInsertSectionExpectation = self.expectation(
forNotification: "listMonitor:didInsertSection:toSectionIndex:",
forNotification: NSNotification.Name(rawValue: "listMonitor:didInsertSection:toSectionIndex:"),
object: observer,
handler: { (note) -> Bool in
@@ -88,7 +88,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
let didInsertObjectExpectation = self.expectation(
forNotification: "listMonitor:didInsertObject:toIndexPath:",
forNotification: NSNotification.Name(rawValue: "listMonitor:didInsertObject:toIndexPath:"),
object: observer,
handler: { (note) -> Bool in
@@ -120,7 +120,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -171,7 +171,7 @@ class ListObserverTests: BaseTestDataTestCase {
let monitor = stack.monitorSectionedList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
@@ -185,7 +185,7 @@ class ListObserverTests: BaseTestDataTestCase {
var events = 0
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -198,62 +198,60 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 0
}
)
for _ in 1 ... 2 {
let didUpdateObjectExpectation = self.expectation(
forNotification: "listMonitor:didUpdateObject:atIndexPath:",
object: observer,
handler: { (note) -> Bool in
let didUpdateObjectExpectation = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitor:didUpdateObject:atIndexPath:"),
object: observer,
handler: { (note) -> Bool in
XCTAssert(events == 1 || events == 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? NSIndexPath
let object = userInfo?["object"] as? TestEntity1
switch object?.testEntityID {
XCTAssert(events == 1 || events == 2)
case NSNumber(value: 101)?:
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:11")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
let indexPath = userInfo?["indexPath"] as? NSIndexPath
let object = userInfo?["object"] as? TestEntity1
case NSNumber(value: 102)?:
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
switch object?.testEntityID {
case NSNumber(value: 101)?:
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:11")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
case NSNumber(value: 102)?:
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:22")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!)
default:
XCTFail()
}
defer {
events += 1
}
return events == 1 || events == 2
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:22")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!)
default:
XCTFail()
}
)
}
defer {
events += 1
}
return events == 1 || events == 2
}
)
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -272,7 +270,7 @@ class ListObserverTests: BaseTestDataTestCase {
if let object = transaction.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
object.testNumber = NSNumber(value: 11)
object.testDecimal = NSDecimalNumber(string: "11")
@@ -286,7 +284,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
if let object = transaction.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
object.testNumber = NSNumber(value: 22)
object.testDecimal = NSDecimalNumber(string: "22")
@@ -325,14 +323,14 @@ class ListObserverTests: BaseTestDataTestCase {
let monitor = stack.monitorSectionedList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
var events = 0
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -346,7 +344,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
let didMoveObjectExpectation = self.expectation(
forNotification: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:",
forNotification: NSNotification.Name(rawValue: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:"),
object: observer,
handler: { (note) -> Bool in
@@ -379,7 +377,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -398,7 +396,7 @@ class ListObserverTests: BaseTestDataTestCase {
if let object = transaction.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
object.testBoolean = NSNumber(value: true)
}
@@ -433,14 +431,14 @@ class ListObserverTests: BaseTestDataTestCase {
let monitor = stack.monitorSectionedList(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
OrderBy<TestEntity1>(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
var events = 0
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -453,40 +451,37 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 0
}
)
for _ in 1 ... 2 {
let didUpdateObjectExpectation = self.expectation(
forNotification: "listMonitor:didDeleteObject:fromIndexPath:",
object: observer,
handler: { (note) -> Bool in
let didUpdateObjectExpectation = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitor:didDeleteObject:fromIndexPath:"),
object: observer,
handler: { (note) -> Bool in
XCTAssert(events == 1 || events == 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? NSIndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.isDeleted, true)
defer {
XCTAssert(events == 1 || events == 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? NSIndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.isDeleted, true)
defer {
events += 1
}
return events == 1 || events == 2
events += 1
}
)
}
return events == 1 || events == 2
}
)
let didDeleteSectionExpectation = self.expectation(
forNotification: "listMonitor:didDeleteSection:fromSectionIndex:",
forNotification: NSNotification.Name(rawValue: "listMonitor:didDeleteSection:fromSectionIndex:"),
object: observer,
handler: { (note) -> Bool in
@@ -514,7 +509,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -531,10 +526,11 @@ class ListObserverTests: BaseTestDataTestCase {
stack.perform(
asynchronous: { (transaction) -> Bool in
transaction.deleteAll(
let count = transaction.deleteAll(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
Where<TestEntity1>(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
)
XCTAssertEqual(count, 2)
return transaction.hasChanges
},
success: { (hasChanges) in

View File

@@ -43,7 +43,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
guard let object = stack.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
XCTFail()
return
@@ -58,7 +58,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
var events = 0
let willUpdateExpectation = self.expectation(
forNotification: "objectMonitor:willUpdateObject:",
forNotification: NSNotification.Name(rawValue: "objectMonitor:willUpdateObject:"),
object: observer,
handler: { (note) -> Bool in
@@ -75,7 +75,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
}
)
let didUpdateExpectation = self.expectation(
forNotification: "objectMonitor:didUpdateObject:changedPersistentKeys:",
forNotification: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),
object: observer,
handler: { (note) -> Bool in
@@ -140,7 +140,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
guard let object = stack.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
Where<TestEntity1>(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
XCTFail()
return
@@ -155,7 +155,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
var events = 0
let didDeleteExpectation = self.expectation(
forNotification: "objectMonitor:didDeleteObject:",
forNotification: NSNotification.Name(rawValue: "objectMonitor:didDeleteObject:"),
object: observer,
handler: { (note) -> Bool in
@@ -219,7 +219,7 @@ class TestObjectObserver: ObjectObserver {
)
}
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, didUpdateObject object: TestEntity1, changedPersistentKeys: Set<KeyPath>) {
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, didUpdateObject object: TestEntity1, changedPersistentKeys: Set<String>) {
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),

View File

@@ -38,21 +38,21 @@ final class OrderByTests: XCTestCase {
do {
let orderBy = OrderBy()
XCTAssertEqual(orderBy, OrderBy([NSSortDescriptor]()))
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key", ascending: false)))
let orderBy = OrderBy<NSManagedObject>()
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>([NSSortDescriptor]()))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(NSSortDescriptor(key: "key", ascending: false)))
XCTAssertTrue(orderBy.sortDescriptors.isEmpty)
}
do {
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
let orderBy = OrderBy(sortDescriptor)
let orderBy = OrderBy<NSManagedObject>(sortDescriptor)
XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
XCTAssertEqual(orderBy, OrderBy(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key1", ascending: false)))
XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(NSSortDescriptor(key: "key1", ascending: false)))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>([sortDescriptor]))
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
}
do {
@@ -61,76 +61,76 @@ final class OrderByTests: XCTestCase {
NSSortDescriptor(key: "key1", ascending: true),
NSSortDescriptor(key: "key2", ascending: false)
]
let orderBy = OrderBy(sortDescriptors)
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
let orderBy = OrderBy<NSManagedObject>(sortDescriptors)
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual(
orderBy,
OrderBy(
OrderBy<NSManagedObject>(
[
NSSortDescriptor(key: "key1", ascending: false),
NSSortDescriptor(key: "key2", ascending: false)
]
)
)
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
}
do {
let orderBy = OrderBy(.ascending("key1"))
let orderBy = OrderBy<NSManagedObject>(.ascending("key1"))
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
XCTAssertEqual(orderBy, OrderBy(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptor))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key2")))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>([sortDescriptor]))
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
}
do {
let orderBy = OrderBy(.ascending("key1"), .descending("key2"))
let orderBy = OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2"))
let sortDescriptors = [
NSSortDescriptor(key: "key1", ascending: true),
NSSortDescriptor(key: "key2", ascending: false)
]
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual(
orderBy,
OrderBy(
OrderBy<NSManagedObject>(
[
NSSortDescriptor(key: "key1", ascending: false),
NSSortDescriptor(key: "key2", ascending: false)
]
)
)
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
}
do {
let sortKeys: [SortKey] = [.ascending("key1"), .descending("key2")]
let orderBy = OrderBy(sortKeys)
let sortKeys: [OrderBy<NSManagedObject>.SortKey] = [.ascending("key1"), .descending("key2")]
let orderBy = OrderBy<NSManagedObject>(sortKeys)
let sortDescriptors = [
NSSortDescriptor(key: "key1", ascending: true),
NSSortDescriptor(key: "key2", ascending: false)
]
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual(
orderBy,
OrderBy(
OrderBy<NSManagedObject>(
[
NSSortDescriptor(key: "key1", ascending: false),
NSSortDescriptor(key: "key2", ascending: false)
]
)
)
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
}
}
@@ -138,15 +138,15 @@ final class OrderByTests: XCTestCase {
@objc
dynamic func test_ThatOrderByClauseOperations_ComputeCorrectly() {
let orderBy1 = OrderBy(.ascending("key1"))
let orderBy2 = OrderBy(.descending("key2"))
let orderBy3 = OrderBy(.ascending("key3"))
let orderBy1 = OrderBy<NSManagedObject>(.ascending("key1"))
let orderBy2 = OrderBy<NSManagedObject>(.descending("key2"))
let orderBy3 = OrderBy<NSManagedObject>(.ascending("key3"))
do {
let plusOrderBy = orderBy1 + orderBy2 + orderBy3
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1")) + OrderBy<NSManagedObject>(.descending("key2"), .ascending("key3")))
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
@@ -158,14 +158,14 @@ final class OrderByTests: XCTestCase {
var plusOrderBy = orderBy1
plusOrderBy += orderBy2
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2")))
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")))
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1")) + OrderBy<NSManagedObject>(.descending("key2")))
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1)
XCTAssertEqual(plusOrderBy.sortDescriptors, orderBy1.sortDescriptors + orderBy2.sortDescriptors)
plusOrderBy += orderBy3
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")) + OrderBy(.ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy<NSManagedObject>(.ascending("key1"), .descending("key2")) + OrderBy<NSManagedObject>(.ascending("key3")))
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
@@ -178,7 +178,7 @@ final class OrderByTests: XCTestCase {
@objc
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
let orderBy = OrderBy(.ascending("key"))
let orderBy = OrderBy<NSManagedObject>(.ascending("key"))
let request = CoreStoreFetchRequest()
orderBy.applyToFetchRequest(request)
XCTAssertNotNil(request.sortDescriptors)

File diff suppressed because it is too large Load Diff

View File

@@ -39,13 +39,13 @@ final class SectionByTests: XCTestCase {
do {
let sectionBy = SectionBy("key")
let sectionBy = SectionBy<NSManagedObject>("key")
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
}
do {
let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } }
let sectionBy = SectionBy<NSManagedObject>("key") { $0.flatMap { "\($0):suffix" } }
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
XCTAssertNil(sectionBy.sectionIndexTransformer(nil))

View File

@@ -38,7 +38,7 @@ final class SelectTests: XCTestCase {
do {
let term: SelectTerm = "attribute"
let term: SelectTerm<NSManagedObject> = "attribute"
XCTAssertEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
@@ -58,7 +58,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.attribute("attribute")
let term = SelectTerm<NSManagedObject>.attribute("attribute")
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
@@ -82,7 +82,7 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.average("attribute")
let term = SelectTerm<NSManagedObject>.average("attribute")
XCTAssertEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
@@ -106,7 +106,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.average("attribute", as: "alias")
let term = SelectTerm<NSManagedObject>.average("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.average("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
@@ -135,7 +135,7 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.count("attribute")
let term = SelectTerm<NSManagedObject>.count("attribute")
XCTAssertEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
@@ -159,7 +159,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.count("attribute", as: "alias")
let term = SelectTerm<NSManagedObject>.count("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.count("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
@@ -188,7 +188,7 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.maximum("attribute")
let term = SelectTerm<NSManagedObject>.maximum("attribute")
XCTAssertEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
@@ -212,7 +212,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.maximum("attribute", as: "alias")
let term = SelectTerm<NSManagedObject>.maximum("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.maximum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
@@ -241,7 +241,7 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.minimum("attribute")
let term = SelectTerm<NSManagedObject>.minimum("attribute")
XCTAssertEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
@@ -265,7 +265,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.minimum("attribute", as: "alias")
let term = SelectTerm<NSManagedObject>.minimum("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.minimum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
@@ -294,7 +294,7 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.sum("attribute")
let term = SelectTerm<NSManagedObject>.sum("attribute")
XCTAssertEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
@@ -318,7 +318,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.sum("attribute", as: "alias")
let term = SelectTerm<NSManagedObject>.sum("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.sum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
@@ -347,7 +347,7 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.objectID()
let term = SelectTerm<NSManagedObject>.objectID()
XCTAssertEqual(term, SelectTerm.objectID())
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
@@ -368,7 +368,7 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.objectID(as: "alias")
let term = SelectTerm<NSManagedObject>.objectID(as: "alias")
XCTAssertEqual(term, SelectTerm.objectID(as: "alias"))
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.objectID())
@@ -393,12 +393,12 @@ final class SelectTests: XCTestCase {
@objc
dynamic func test_ThatSelectClauses_ConfigureCorrectly() {
let term1 = SelectTerm.attribute("attribute1")
let term2 = SelectTerm.attribute("attribute2")
let term3 = SelectTerm.attribute("attribute3")
let term1 = SelectTerm<NSManagedObject>.attribute("attribute1")
let term2 = SelectTerm<NSManagedObject>.attribute("attribute2")
let term3 = SelectTerm<NSManagedObject>.attribute("attribute3")
do {
let select = Select<Int>(term1, term2, term3)
let select = Select<NSManagedObject, Int>(term1, term2, term3)
XCTAssertEqual(select.selectTerms, [term1, term2, term3])
XCTAssertNotEqual(select.selectTerms, [term1, term3, term2])
XCTAssertNotEqual(select.selectTerms, [term2, term1, term3])
@@ -408,7 +408,7 @@ final class SelectTests: XCTestCase {
}
do {
let select = Select<Int>([term1, term2, term3])
let select = Select<NSManagedObject, Int>([term1, term2, term3])
XCTAssertEqual(select.selectTerms, [term1, term2, term3])
XCTAssertNotEqual(select.selectTerms, [term1, term3, term2])
XCTAssertNotEqual(select.selectTerms, [term2, term1, term3])

View File

@@ -37,9 +37,10 @@ class SetupTests: BaseTestDataTestCase {
do {
let schemaHistory = SchemaHistory(
modelName: "Model",
bundle: Bundle(for: type(of: self)),
migrationChain: nil
XcodeDataModelSchema.from(
modelName: "Model",
bundle: Bundle(for: type(of: self))
)
)
let stack = DataStack(schemaHistory: schemaHistory)
XCTAssertEqual(stack.coordinator.managedObjectModel, schemaHistory.rawModel)
@@ -66,7 +67,7 @@ class SetupTests: BaseTestDataTestCase {
let stack = self.expectLogger([.logWarning]) {
DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)),
migrationChain: migrationChain
)
@@ -83,7 +84,7 @@ class SetupTests: BaseTestDataTestCase {
dynamic func test_ThatInMemoryStores_SetupCorrectly() {
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
@@ -138,7 +139,7 @@ class SetupTests: BaseTestDataTestCase {
dynamic func test_ThatSQLiteStores_SetupCorrectly() {
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
@@ -206,7 +207,7 @@ class SetupTests: BaseTestDataTestCase {
do {
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try! stack.addStorageAndWait(sqliteStore)
@@ -225,10 +226,10 @@ class SetupTests: BaseTestDataTestCase {
let metadata = try createStore()
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try sqliteStore.eraseStorageAndWait(
try sqliteStore.cs_eraseStorageAndWait(
metadata: metadata,
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
)
@@ -243,7 +244,7 @@ class SetupTests: BaseTestDataTestCase {
do {
let metadata = try createStore()
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
try sqliteStore.cs_eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
@@ -258,7 +259,7 @@ class SetupTests: BaseTestDataTestCase {
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
@@ -326,7 +327,7 @@ class SetupTests: BaseTestDataTestCase {
do {
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try! stack.addStorageAndWait(sqliteStore)
@@ -345,10 +346,10 @@ class SetupTests: BaseTestDataTestCase {
let metadata = try createStore()
let stack = DataStack(
modelName: "Model",
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try sqliteStore.eraseStorageAndWait(
try sqliteStore.cs_eraseStorageAndWait(
metadata: metadata,
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
)
@@ -363,7 +364,7 @@ class SetupTests: BaseTestDataTestCase {
do {
let metadata = try createStore()
try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
try sqliteStore.cs_eraseStorageAndWait(metadata: metadata, soureModelHint: nil)
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))

View File

@@ -396,7 +396,7 @@ final class TransactionTests: BaseTestCase {
let observer = TestListObserver()
let monitor = stack.monitorList(
From<TestEntity1>(),
OrderBy(.ascending("testEntityID"))
OrderBy<TestEntity1>(.ascending("testEntityID"))
)
monitor.addObserver(observer)
@@ -404,7 +404,7 @@ final class TransactionTests: BaseTestCase {
var events = 0
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -418,7 +418,7 @@ final class TransactionTests: BaseTestCase {
}
)
let didInsertObjectExpectation = self.expectation(
forNotification: "listMonitor:didInsertObject:toIndexPath:",
forNotification: NSNotification.Name(rawValue: "listMonitor:didInsertObject:toIndexPath:"),
object: observer,
handler: { (note) -> Bool in
@@ -448,7 +448,7 @@ final class TransactionTests: BaseTestCase {
}
)
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
forNotification: NSNotification.Name(rawValue: "listMonitorDidChange:"),
object: observer,
handler: { (note) -> Bool in
@@ -737,7 +737,7 @@ final class TransactionTests: BaseTestCase {
createDiscardExpectation.fulfill()
try transaction.cancel()
},
success: {
success: { _ in
XCTFail()
},
@@ -795,7 +795,7 @@ final class TransactionTests: BaseTestCase {
try transaction.cancel()
},
success: {
success: { _ in
XCTFail()
},
@@ -828,7 +828,7 @@ final class TransactionTests: BaseTestCase {
try transaction.cancel()
},
success: {
success: { _ in
XCTFail()
},

View File

@@ -31,12 +31,12 @@ import CoreStore
// MARK: - XCTAssertAllEqual
private func XCTAssertAllEqual(_ whereClauses: Where...) {
private func XCTAssertAllEqual<D>(_ whereClauses: Where<D>...) {
XCTAssertAllEqual(whereClauses)
}
private func XCTAssertAllEqual(_ whereClauses: [Where]) {
private func XCTAssertAllEqual<D>(_ whereClauses: [Where<D>]) {
for i in whereClauses.indices {
@@ -52,56 +52,62 @@ private func XCTAssertAllEqual(_ whereClauses: [Where]) {
final class WhereTests: XCTestCase {
@objc
dynamic func test_ThatDynamicModelKeyPaths_CanBeCreated() {
XCTAssertEqual(String(keyPath: \TestEntity1.testEntityID), "testEntityID")
}
@objc
dynamic func test_ThatWhereClauses_ConfigureCorrectly() {
do {
let whereClause = Where()
XCTAssertEqual(whereClause, Where(true))
XCTAssertNotEqual(whereClause, Where(false))
let whereClause = Where<NSManagedObject>()
XCTAssertEqual(whereClause, Where<NSManagedObject>(true))
XCTAssertNotEqual(whereClause, Where<NSManagedObject>(false))
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
}
do {
let whereClause = Where(true)
XCTAssertEqual(whereClause, Where())
XCTAssertNotEqual(whereClause, Where(false))
let whereClause = Where<NSManagedObject>(true)
XCTAssertEqual(whereClause, Where<NSManagedObject>())
XCTAssertNotEqual(whereClause, Where<NSManagedObject>(false))
XCTAssertEqual(whereClause.predicate, NSPredicate(value: true))
}
do {
let predicate = NSPredicate(format: "%K == %@", "key", "value")
let whereClause = Where(predicate)
XCTAssertEqual(whereClause, Where(predicate))
let whereClause = Where<NSManagedObject>(predicate)
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where("%K == %@", "key", "value")
let whereClause = Where<NSManagedObject>("%K == %@", "key", "value")
let predicate = NSPredicate(format: "%K == %@", "key", "value")
XCTAssertEqual(whereClause, Where(predicate))
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where("%K == %@", argumentArray: ["key", "value"])
let whereClause = Where<NSManagedObject>("%K == %@", argumentArray: ["key", "value"])
let predicate = NSPredicate(format: "%K == %@", "key", "value")
XCTAssertEqual(whereClause, Where(predicate))
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where("key", isEqualTo: "value")
let whereClause = Where<NSManagedObject>("key", isEqualTo: "value")
let predicate = NSPredicate(format: "%K == %@", "key", "value")
XCTAssertEqual(whereClause, Where(predicate))
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
}
do {
let whereClause = Where("key", isMemberOf: ["value1", "value2", "value3"])
let whereClause = Where<NSManagedObject>("key", isMemberOf: ["value1", "value2", "value3"])
let predicate = NSPredicate(format: "%K IN %@", "key", ["value1", "value2", "value3"])
XCTAssertEqual(whereClause, Where(predicate))
XCTAssertEqual(whereClause, Where<NSManagedObject>(predicate))
XCTAssertEqual(whereClause.predicate, predicate)
}
}
@@ -113,112 +119,112 @@ final class WhereTests: XCTestCase {
let value: Int = 100
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))
Where<NSManagedObject>("%K == %d", "key", value),
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
Where<NSManagedObject>("%K == %d", "key", NSNumber(value: value)),
Where<NSManagedObject>("%K == %@", "key", value),
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
Where<NSManagedObject>("%K == %@", "key", NSNumber(value: value)),
Where<NSManagedObject>("key", isEqualTo: value),
Where<NSManagedObject>("key", isEqualTo: NSNumber(value: value))
)
}
do {
let value = NSNumber(value: 100)
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)
Where<NSManagedObject>("%K == %d", "key", value),
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
Where<NSManagedObject>("%K == %d", "key", value.intValue),
Where<NSManagedObject>("%K == %@", "key", value),
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
Where<NSManagedObject>("%K == %@", "key", value.intValue),
Where<NSManagedObject>("key", isEqualTo: value),
Where<NSManagedObject>("key", isEqualTo: value.intValue)
)
}
do {
let value: Int64 = Int64.max
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))
Where<NSManagedObject>("%K == %d", "key", value),
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
Where<NSManagedObject>("%K == %d", "key", NSNumber(value: value)),
Where<NSManagedObject>("%K == %@", "key", value),
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
Where<NSManagedObject>("%K == %@", "key", NSNumber(value: value)),
Where<NSManagedObject>("key", isEqualTo: value),
Where<NSManagedObject>("key", isEqualTo: NSNumber(value: value))
)
}
do {
let value = NSNumber(value: Int64.max)
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)
Where<NSManagedObject>("%K == %d", "key", value),
Where<NSManagedObject>("%K == %d", "key", value as AnyObject),
Where<NSManagedObject>("%K == %d", "key", value.int64Value),
Where<NSManagedObject>("%K == %@", "key", value),
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
Where<NSManagedObject>("%K == %@", "key", value.int64Value),
Where<NSManagedObject>("key", isEqualTo: value),
Where<NSManagedObject>("key", isEqualTo: value.int64Value)
)
}
do {
let value: String = "value"
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))
Where<NSManagedObject>("%K == %s", "key", value),
Where<NSManagedObject>("%K == %s", "key", value as AnyObject),
Where<NSManagedObject>("%K == %s", "key", NSString(string: value)),
Where<NSManagedObject>("%K == %@", "key", value),
Where<NSManagedObject>("%K == %@", "key", value as AnyObject),
Where<NSManagedObject>("%K == %@", "key", NSString(string: value)),
Where<NSManagedObject>("key", isEqualTo: value),
Where<NSManagedObject>("key", isEqualTo: value as NSString),
Where<NSManagedObject>("key", isEqualTo: NSString(string: value))
)
}
do {
let value = NSString(string: "value")
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)
Where<NSManagedObject>("%K == %s", "key", value),
Where<NSManagedObject>("%K == %s", "key", value as String),
Where<NSManagedObject>("%K == %s", "key", value as String as AnyObject),
Where<NSManagedObject>("%K == %@", "key", value),
Where<NSManagedObject>("%K == %@", "key", value as String),
Where<NSManagedObject>("%K == %@", "key", value as String as AnyObject),
Where<NSManagedObject>("key", isEqualTo: value),
Where<NSManagedObject>("key", isEqualTo: value as String),
Where<NSManagedObject>("key", isEqualTo: value as String as NSString)
)
}
do {
let value: [Int] = [100, 200]
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)
Where<NSManagedObject>("%K IN %@", "key", value),
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject),
Where<NSManagedObject>("%K IN %@", "key", value as [AnyObject]),
Where<NSManagedObject>("%K IN %@", "key", value as NSArray),
Where<NSManagedObject>("%K IN %@", "key", NSArray(array: value)),
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject as! NSArray),
Where<NSManagedObject>("key", isMemberOf: value)
)
}
do {
let value: [Int64] = [Int64.min, 100, Int64.max]
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)
Where<NSManagedObject>("%K IN %@", "key", value),
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject),
Where<NSManagedObject>("%K IN %@", "key", value as [AnyObject]),
Where<NSManagedObject>("%K IN %@", "key", value as NSArray),
Where<NSManagedObject>("%K IN %@", "key", NSArray(array: value)),
Where<NSManagedObject>("%K IN %@", "key", value as AnyObject as! NSArray),
Where<NSManagedObject>("key", isMemberOf: value)
)
}
}
@@ -226,9 +232,9 @@ final class WhereTests: XCTestCase {
@objc
dynamic func test_ThatWhereClauseOperations_ComputeCorrectly() {
let whereClause1 = Where("key1", isEqualTo: "value1")
let whereClause2 = Where("key2", isEqualTo: "value2")
let whereClause3 = Where("key3", isEqualTo: "value3")
let whereClause1 = Where<NSManagedObject>("key1", isEqualTo: "value1")
let whereClause2 = Where<NSManagedObject>("key2", isEqualTo: "value2")
let whereClause3 = Where<NSManagedObject>("key3", isEqualTo: "value3")
do {
@@ -256,6 +262,21 @@ final class WhereTests: XCTestCase {
XCTAssertEqual(andWhere.predicate, andPredicate)
XCTAssertEqual(andWhere, whereClause1 && whereClause2 && whereClause3)
}
do {
let andWhere = whereClause1 && whereClause2 && whereClause3
let noneWhere: Where<NSManagedObject>? = nil
let someWhere: Where<NSManagedObject>? = Where<NSManagedObject>("key4", isEqualTo: "value4")
let finalNoneWhere = andWhere &&? noneWhere
let finalSomeWhere = andWhere &&? someWhere
let unwrappedFinalSomeWhere = andWhere && someWhere!
XCTAssertEqual(andWhere.predicate, finalNoneWhere.predicate)
XCTAssertEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
}
do {
let orWhere = whereClause1 || whereClause2 || whereClause3
@@ -272,12 +293,27 @@ final class WhereTests: XCTestCase {
XCTAssertEqual(orWhere.predicate, orPredicate)
XCTAssertEqual(orWhere, whereClause1 || whereClause2 || whereClause3)
}
do {
let orWhere = whereClause1 || whereClause2 || whereClause3
let noneWhere: Where<NSManagedObject>? = nil
let someWhere: Where<NSManagedObject>? = Where<NSManagedObject>("key4", isEqualTo: "value4")
let finalNoneWhere = orWhere &&? noneWhere
let finalSomeWhere = orWhere &&? someWhere
let unwrappedFinalSomeWhere = orWhere && someWhere!
XCTAssertEqual(orWhere.predicate, finalNoneWhere.predicate)
XCTAssertEqual(finalSomeWhere.predicate, unwrappedFinalSomeWhere.predicate)
}
}
@objc
dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() {
let whereClause = Where("key", isEqualTo: "value")
let whereClause = Where<NSManagedObject>("key", isEqualTo: "value")
let request = CoreStoreFetchRequest()
whereClause.applyToFetchRequest(request)
XCTAssertNotNil(request.predicate)

1110
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -30,17 +30,43 @@ import CoreData
// MARK: - AsynchronousDataTransaction
/**
The `AsynchronousDataTransaction` provides an interface for `NSManagedObject` creates, updates, and deletes. A transaction object should typically be only used from within a transaction block initiated from `DataStack.beginAsynchronous(_:)`, or from `CoreStore.beginAsynchronous(_:)`.
The `AsynchronousDataTransaction` provides an interface for `DynamicObject` creates, updates, and deletes. A transaction object should typically be only used from within a transaction block initiated from `DataStack.perform(asynchronous:...)`, or from `CoreStore.perform(synchronous:...)`.
*/
public final class AsynchronousDataTransaction: BaseDataTransaction {
/**
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.
*/
public func cancel() throws -> Never {
throw CoreStoreError.userCancelled
}
// MARK: - Result
/**
The `Result` contains the success or failure information for a completed transaction
*/
public enum Result<T> {
/**
`Result<T>.success` indicates that the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated `userInfo` is the value returned from the transaction closure.
*/
case success(userInfo: T)
/**
`Result<T>.failure` indicates that the transaction either failed or was cancelled. The associated object for this value is a `CoreStoreError` enum value.
*/
case failure(error: CoreStoreError)
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var boolValue: Bool {
switch self {
@@ -64,22 +90,8 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
}
// MARK: -
/**
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.
*/
public func cancel() throws -> Never {
throw CoreStoreError.userCancelled
}
// MARK: BaseDataTransaction
/**
@@ -88,7 +100,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/
public override func create<T: DynamicObject>(_ into: Into<T>) -> T {
public override func create<D>(_ into: Into<D>) -> D {
CoreStore.assert(
!self.isCommitted,
@@ -99,12 +111,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
/**
Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once.
Returns an editable proxy of a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be edited
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public override func edit<T: DynamicObject>(_ object: T?) -> T? {
public override func edit<D: DynamicObject>(_ object: D?) -> D? {
CoreStore.assert(
!self.isCommitted,
@@ -115,13 +127,13 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
/**
Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `commit()` method was already called once.
Returns an editable proxy of the object with the specified `NSManagedObjectID`.
- parameter into: an `Into` clause specifying the entity type
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public override func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public override func edit<D>(_ into: Into<D>, _ objectID: NSManagedObjectID) -> D? {
CoreStore.assert(
!self.isCommitted,
@@ -132,11 +144,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
/**
Deletes a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once.
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` type to be deleted
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
*/
public override func delete<T: DynamicObject>(_ object: T?) {
public override func delete<D: DynamicObject>(_ object: D?) {
CoreStore.assert(
!self.isCommitted,
@@ -147,13 +159,13 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
/**
Deletes the specified `NSManagedObject`s.
Deletes the specified `DynamicObject`s.
- parameter object1: the `NSManagedObject` type to be deleted
- parameter object2: another `NSManagedObject` type to be deleted
- parameter objects: other `NSManagedObject`s type to be deleted
- parameter object1: the `DynamicObject` to be deleted
- parameter object2: another `DynamicObject` to be deleted
- parameter objects: other `DynamicObject`s to be deleted
*/
public override func delete<T: DynamicObject>(_ object1: T?, _ object2: T?, _ objects: T?...) {
public override func delete<D: DynamicObject>(_ object1: D?, _ object2: D?, _ objects: D?...) {
CoreStore.assert(
!self.isCommitted,
@@ -164,11 +176,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
/**
Deletes the specified `NSManagedObject`s.
Deletes the specified `DynamicObject`s.
- parameter objects: the `NSManagedObject`s type to be deleted
- parameter objects: the `DynamicObject`s to be deleted
*/
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
CoreStore.assert(
!self.isCommitted,
@@ -191,23 +203,19 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
self.isCommitted = true
let group = DispatchGroup()
group.enter()
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
self.context.saveAsynchronouslyWithCompletion { (hasChanges, error) -> Void in
completion(result.0, result.1)
self.result = result
completion(hasChanges, error)
self.result = (hasChanges, error)
group.leave()
}
group.wait()
self.context.reset()
}
// 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 }) {
@@ -219,22 +227,19 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
!self.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.autoCommit { (result) in
self.autoCommit { (hasChanges, error) in
switch result {
if let error = error {
case (let hasChanges, nil): completion(SaveResult(hasChanges: hasChanges))
case (_, let error?): completion(SaveResult(error))
completion(SaveResult(error))
}
else {
completion(SaveResult(hasChanges: hasChanges))
}
}
}
/**
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? {
@@ -265,9 +270,9 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
}
switch childTransaction.result {
case nil: return nil
case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges)
case (_, let error?)?: return SaveResult(error)
case .none: return nil
case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
case .some(_, let error?): return SaveResult(error)
}
}
}

View File

@@ -0,0 +1,47 @@
//
// AttributeProtocol.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - AttributeProtocol
internal protocol AttributeProtocol: class {
static var attributeType: NSAttributeType { get }
var keyPath: KeyPathString { get }
var isOptional: Bool { get }
var isIndexed: Bool { get }
var isTransient: Bool { get }
var versionHashModifier: () -> String? { get }
var renamingIdentifier: () -> String? { get }
var defaultValue: () -> Any? { get }
var affectedByKeyPaths: () -> Set<String> { get }
weak var parentObject: CoreStoreObject? { get set }
var getter: CoreStoreManagedObject.CustomGetter? { get }
var setter: CoreStoreManagedObject.CustomSetter? { get }
}

View File

@@ -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: DynamicObject & ImportableObject>(
_ into: Into<T>,
source: T.ImportSource) throws -> T? {
public func importObject<D: ImportableObject>(
_ into: Into<D>,
source: D.ImportSource) throws -> D? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -69,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: DynamicObject & ImportableObject>(
_ object: T,
source: T.ImportSource) throws {
public func importObject<D: ImportableObject>(
_ object: D,
source: D.ImportSource) throws {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -97,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: DynamicObject & ImportableObject, S: Sequence>(
_ into: Into<T>,
sourceArray: S) throws -> [T] where S.Iterator.Element == T.ImportSource {
public func importObjects<D: ImportableObject, S: Sequence>(
_ into: Into<D>,
sourceArray: S) throws -> [D] where S.Iterator.Element == D.ImportSource {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -108,7 +108,7 @@ public extension BaseDataTransaction {
return try autoreleasepool {
return try sourceArray.flatMap { (source) -> T? in
return try sourceArray.flatMap { (source) -> D? in
let entityType = into.entityClass
guard entityType.shouldInsert(from: source, in: self) else {
@@ -133,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: DynamicObject & ImportableUniqueObject>(
_ into: Into<T>,
source: T.ImportSource) throws -> T? {
public func importUniqueObject<D: ImportableUniqueObject>(
_ into: Into<D>,
source: D.ImportSource) throws -> D? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -151,7 +151,7 @@ public extension BaseDataTransaction {
return nil
}
if let object = self.fetchOne(From(entityType), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
if let object = self.fetchOne(From(entityType), Where<D>(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
guard entityType.shouldUpdate(from: source, in: self) else {
@@ -177,7 +177,7 @@ public extension BaseDataTransaction {
/**
Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources.
`ImportableUniqueObject` methods are called on the objects in the same order as they are in the `sourceArray`, and are returned in an array with that same order.
- Warning: If `sourceArray` contains multiple import sources with same ID, no merging will occur and ONLY THE LAST duplicate will be imported.
- Warning: If `sourceArray` contains multiple import sources with same ID, only the last `ImportSource` of the duplicates will be imported.
- parameter into: an `Into` clause specifying the entity type
- parameter sourceArray: the array of objects to import values from
@@ -185,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: DynamicObject & ImportableUniqueObject, S: Sequence>(
_ into: Into<T>,
public func importUniqueObjects<D: ImportableUniqueObject, S: Sequence>(
_ into: Into<D>,
sourceArray: S,
preProcess: @escaping (_ mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] where S.Iterator.Element == T.ImportSource {
preProcess: @escaping (_ mapping: [D.UniqueIDType: D.ImportSource]) throws -> [D.UniqueIDType: D.ImportSource] = { $0 }) throws -> [D] where S.Iterator.Element == D.ImportSource {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -198,10 +198,10 @@ public extension BaseDataTransaction {
return try autoreleasepool {
let entityType = into.entityClass
var importSourceByID = Dictionary<T.UniqueIDType, T.ImportSource>()
var importSourceByID = Dictionary<D.UniqueIDType, D.ImportSource>()
let sortedIDs = try autoreleasepool {
return try sourceArray.flatMap { (source) -> T.UniqueIDType? in
return try sourceArray.flatMap { (source) -> D.UniqueIDType? in
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
@@ -214,12 +214,12 @@ public extension BaseDataTransaction {
importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
var existingObjectsByID = Dictionary<T.UniqueIDType, T>()
self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
var existingObjectsByID = Dictionary<D.UniqueIDType, D>()
self.fetchAll(From(entityType), Where<D>(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
var processedObjectIDs = Set<T.UniqueIDType>()
var result = [T]()
var processedObjectIDs = Set<D.UniqueIDType>()
var result = [D]()
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {

View File

@@ -32,96 +32,113 @@ import CoreData
extension BaseDataTransaction: FetchableSource, QueryableSource {
/**
Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Deletes all `DynamicObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number of `NSManagedObject`s deleted
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
public func deleteAll<D>(_ from: From<D>, _ deleteClauses: DeleteClause...) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.deleteAll(from, deleteClauses)
}
/**
Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Deletes all `DynamicObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number of `NSManagedObject`s deleted
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
public func deleteAll<D>(_ from: From<D>, _ deleteClauses: [DeleteClause]) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.deleteAll(from, deleteClauses)
}
/**
Deletes all `DynamicObject`s that satisfy the specified conditions.
```
transaction.deleteAll(From<Person>().where(\.age > 50))
```
- parameter clauseChain: a `FetchChainableBuilderType` clause chain created from a `From` clause
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.deleteAll(from, deleteClauses)
return self.context.deleteAll(clauseChain.from, clauseChain.fetchClauses)
}
// MARK: FetchableSource
/**
Fetches the `NSManagedObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
Fetches the `DynamicObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
- parameter object: a reference to the object created/fetched outside the transaction
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
*/
public func fetchExisting<T: DynamicObject>(_ object: T) -> T? {
public func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
return self.context.fetchExisting(object)
}
/**
Fetches the `NSManagedObject` instance in the transaction's context from an `NSManagedObjectID`.
Fetches the `DynamicObject` instance in the transaction's context from an `NSManagedObjectID`.
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
- returns: the `DynamicObject` instance if the object exists in the transaction, or `nil` if not found.
*/
public func fetchExisting<T: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
public func fetchExisting<D: DynamicObject>(_ objectID: NSManagedObjectID) -> D? {
return self.context.fetchExisting(objectID)
}
/**
Fetches the `NSManagedObject` instances in the transaction's context from references created from a transaction or from a different managed object context.
Fetches the `DynamicObject` instances in the transaction's context from references created from a transaction or from a different managed object context.
- parameter objects: an array of `NSManagedObject`s created/fetched outside the transaction
- returns: the `NSManagedObject` array for objects that exists in the transaction
- parameter objects: an array of `DynamicObject`s created/fetched outside the transaction
- returns: the `DynamicObject` array for objects that exists in the transaction
*/
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objects: S) -> [D] where S.Iterator.Element == D {
return self.context.fetchExisting(objects)
}
/**
Fetches the `NSManagedObject` instances in the transaction's context from a list of `NSManagedObjectID`.
Fetches the `DynamicObject` instances in the transaction's context from a list of `NSManagedObjectID`.
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the transaction
- returns: the `DynamicObject` array for objects that exists in the transaction
*/
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objectIDs: S) -> [D] where S.Iterator.Element == NSManagedObjectID {
return self.context.fetchExisting(objectIDs)
}
/**
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
public func fetchOne<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> D? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -131,13 +148,13 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
public func fetchOne<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> D? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -147,13 +164,34 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeen = transaction.fetchOne(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`
*/
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) -> B.ObjectType? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchOne(clauseChain)
}
/**
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
public func fetchAll<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [D]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -163,13 +201,13 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
public func fetchAll<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [D]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -179,13 +217,34 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let people = transaction.fetchAll(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`
*/
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> [B.ObjectType]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchAll(clauseChain)
}
/**
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
public func fetchCount<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -195,13 +254,13 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
public func fetchCount<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -211,13 +270,34 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let numberOfAdults = transaction.fetchCount(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchCount(clauseChain)
}
/**
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
public func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -227,13 +307,13 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
public func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -243,13 +323,34 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeenID = transaction.fetchObjectID(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`
*/
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) -> NSManagedObjectID? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchObjectID(clauseChain)
}
/**
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
public func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -259,13 +360,13 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
public func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -274,6 +375,27 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
return self.context.fetchObjectIDs(from, fetchClauses)
}
/**
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let idsOfAdults = transaction.fetchObjectIDs(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) -> [NSManagedObjectID]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchObjectIDs(clauseChain)
}
// MARK: QueryableSource
@@ -287,7 +409,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
public func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) -> U? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -306,7 +428,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
public func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) -> U? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -315,6 +437,29 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
return self.context.queryValue(from, selectClause, queryClauses)
}
/**
Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
```
let averageAdultAge = transaction.queryValue(
From<MyPersonEntity>()
.select(Int.self, .average(\.age))
.where(\.age > 18)
)
```
- parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request.
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
*/
public func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
}
/**
Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
@@ -325,7 +470,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
public func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -344,7 +489,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
public func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -353,6 +498,38 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
return self.context.queryAttributes(from, selectClause, queryClauses)
}
/**
Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
```
let results = dataStack.queryAttributes(
From<MyPersonEntity>()
.select(
NSDictionary.self,
.attribute(\.age, as: "age"),
.count(\.age, as: "numberOfPeople")
)
.groupBy(\.age)
)
for dictionary in results! {
let age = dictionary["age"] as! Int
let count = dictionary["numberOfPeople"] as! Int
print("There are \(count) people who are \(age) years old."
}
```
- parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request.
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
*/
public func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
}
// MARK: FetchableSource, QueryableSource
@@ -365,11 +542,11 @@ extension BaseDataTransaction: FetchableSource, QueryableSource {
}
// MARK: Deprecated
// MARK: Obsoleted
@available(*, deprecated, renamed: "unsafeContext()")
@available(*, obsoleted: 3.1, renamed: "unsafeContext()")
public func internalContext() -> NSManagedObjectContext {
return self.unsafeContext()
fatalError()
}
}

View File

@@ -50,7 +50,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/
public func create<T: DynamicObject>(_ into: Into<T>) -> T {
public func create<D>(_ into: Into<D>) -> D {
let entityClass = into.entityClass
CoreStore.assert(
@@ -116,12 +116,12 @@ public /*abstract*/ class BaseDataTransaction {
}
/**
Returns an editable proxy of a specified `NSManagedObject`.
Returns an editable proxy of a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
- parameter object: the `NSManagedObject` or `CoreStoreObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public func edit<T: DynamicObject>(_ object: T?) -> T? {
public func edit<D: DynamicObject>(_ object: D?) -> D? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -139,9 +139,9 @@ public /*abstract*/ class BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
- returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`.
*/
public func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public func edit<D>(_ into: Into<D>, _ objectID: NSManagedObjectID) -> D? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -156,11 +156,11 @@ public /*abstract*/ class BaseDataTransaction {
}
/**
Deletes a specified `NSManagedObject`.
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` to be deleted
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
*/
public func delete<T: DynamicObject>(_ object: T?) {
public func delete<D: DynamicObject>(_ object: D?) {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -173,21 +173,21 @@ public /*abstract*/ class BaseDataTransaction {
}
/**
Deletes the specified `NSManagedObject`s.
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s.
- parameter object1: the `NSManagedObject` to be deleted
- parameter object2: another `NSManagedObject` to be deleted
- parameter objects: other `NSManagedObject`s to be deleted
- parameter object1: the `NSManagedObject` or `CoreStoreObject` to be deleted
- parameter object2: another `NSManagedObject` or `CoreStoreObject` to be deleted
- parameter objects: other `NSManagedObject`s or `CoreStoreObject`s to be deleted
*/
public func delete<T: DynamicObject>(_ object1: T?, _ object2: T?, _ objects: T?...) {
public func delete<D: DynamicObject>(_ object1: D?, _ object2: D?, _ objects: D?...) {
self.delete(([object1, object2] + objects).flatMap { $0 })
}
/**
Deletes the specified `NSManagedObject`s.
Deletes the specified `NSManagedObject`s or `CoreStoreObject`s.
- parameter objects: the `NSManagedObject`s to be deleted
- parameter objects: the `NSManagedObject`s or `CoreStoreObject`s to be deleted
*/
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
@@ -215,30 +215,12 @@ public /*abstract*/ class BaseDataTransaction {
// MARK: Inspecting Pending Objects
/**
Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- returns: a `Set` of pending `NSManagedObject`s that were inserted to the transaction.
*/
public func insertedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
)
return self.context.insertedObjects
}
/**
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
Returns all pending `DynamicObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were inserted to the transaction.
*/
public func insertedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
public func insertedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
@@ -248,7 +230,7 @@ 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 })
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
/**
@@ -272,10 +254,10 @@ public /*abstract*/ class BaseDataTransaction {
/**
Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/
public func insertedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
public func insertedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
@@ -285,15 +267,16 @@ 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 })
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}
/**
Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `commit()` method was called.
Returns all pending `DynamicObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- returns: a `Set` of pending `NSManagedObject`s that were updated to the transaction.
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were updated in the transaction.
*/
public func updatedObjects() -> Set<NSManagedObject> {
public func updatedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
@@ -303,26 +286,7 @@ public /*abstract*/ class BaseDataTransaction {
!self.isCommitted,
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
)
return self.context.updatedObjects
}
/**
Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
*/
public func updatedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
)
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
/**
@@ -346,10 +310,10 @@ public /*abstract*/ class BaseDataTransaction {
/**
Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/
public func updatedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
public func updatedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
@@ -359,15 +323,16 @@ 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 })
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}
/**
Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `commit()` method was called.
Returns all pending `DynamicObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- returns: a `Set` of pending `NSManagedObject`s that were deleted from the transaction.
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were deleted from the transaction.
*/
public func deletedObjects() -> Set<NSManagedObject> {
public func deletedObjects<D: DynamicObject>(_ entity: D.Type) -> Set<D> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
@@ -377,32 +342,13 @@ public /*abstract*/ class BaseDataTransaction {
!self.isCommitted,
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
)
return self.context.deletedObjects
}
/**
Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
*/
public func deletedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
)
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
@@ -421,10 +367,10 @@ public /*abstract*/ class BaseDataTransaction {
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
public func deletedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
public func deletedObjectIDs<D: DynamicObject>(_ entity: D.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
@@ -434,7 +380,7 @@ 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 })
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}
@@ -450,7 +396,7 @@ public /*abstract*/ class BaseDataTransaction {
```
- Important: Do not use this method to store thread-sensitive data.
*/
private let userInfo = UserInfo()
public let userInfo = UserInfo()
// MARK: Internal
@@ -491,4 +437,54 @@ public /*abstract*/ class BaseDataTransaction {
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
}
deinit {
self.context.reset()
}
// MARK: Deprecated
@available(*, deprecated, message: "Use insertedObjects(_:) and pass the specific entity type")
public func insertedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
)
return self.context.insertedObjects
}
@available(*, deprecated, message: "Use updatedObjects(_:) and pass the specific entity type")
public func updatedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
)
return self.context.updatedObjects
}
@available(*, deprecated, message: "Use deletedObjects(_:) and pass the specific entity type")
public func deletedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
)
return self.context.deletedObjects
}
}

View File

@@ -35,12 +35,13 @@ import CoreData
- SeeAlso: `AsynchronousDataTransaction`
*/
@objc
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
public final class CSAsynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
/**
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
- parameter success: the block executed if the save succeeds.
- parameter failure: the block executed if the save fails. A `CSError` is reported as the argument of the block.
*/
@objc
public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
@@ -53,12 +54,15 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.bridgeToSwift.autoCommit { (result) in
self.bridgeToSwift.autoCommit { (_, error) in
switch result {
if let error = error {
case (_, nil): success?()
case (_, let error?): failure?(error.bridgeToObjectiveC)
failure?(error.bridgeToObjectiveC)
}
else {
success?()
}
}
}
@@ -138,9 +142,9 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
public typealias SwiftType = AsynchronousDataTransaction
public override var bridgeToSwift: AsynchronousDataTransaction {
public var bridgeToSwift: AsynchronousDataTransaction {
return super.bridgeToSwift as! AsynchronousDataTransaction
return super.swiftTransaction as! AsynchronousDataTransaction
}
public required init(_ swiftValue: AsynchronousDataTransaction) {
@@ -148,19 +152,14 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
super.init(swiftValue as BaseDataTransaction)
}
public required init(_ swiftValue: BaseDataTransaction) {
public required override init(_ swiftValue: BaseDataTransaction) {
super.init(swiftValue as! AsynchronousDataTransaction)
super.init(swiftValue)
}
// 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)?) {
@@ -179,12 +178,6 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
}
}
/**
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

View File

@@ -40,7 +40,7 @@ public extension CSBaseDataTransaction {
@objc
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
return self.bridgeToSwift.context.fetchExisting(object) as NSManagedObject?
return self.swiftTransaction.context.fetchExisting(object) as NSManagedObject?
}
/**
@@ -52,7 +52,7 @@ public extension CSBaseDataTransaction {
@objc
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
return self.bridgeToSwift.context.fetchExisting(objectID) as NSManagedObject?
return self.swiftTransaction.context.fetchExisting(objectID) as NSManagedObject?
}
/**
@@ -64,7 +64,7 @@ public extension CSBaseDataTransaction {
@objc
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
return self.bridgeToSwift.context.fetchExisting(objects) as [NSManagedObject]
return self.swiftTransaction.context.fetchExisting(objects) as [NSManagedObject]
}
/**
@@ -76,7 +76,7 @@ public extension CSBaseDataTransaction {
@objc
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
return self.bridgeToSwift.context.fetchExisting(objectIDs) as [NSManagedObject]
return self.swiftTransaction.context.fetchExisting(objectIDs) as [NSManagedObject]
}
/**
@@ -90,10 +90,10 @@ public extension CSBaseDataTransaction {
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(),
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.bridgeToSwift.context.fetchOne(from, fetchClauses)
return self.swiftTransaction.context.fetchOne(from, fetchClauses)
}
/**
@@ -107,10 +107,10 @@ public extension CSBaseDataTransaction {
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(),
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.bridgeToSwift.context.fetchAll(from, fetchClauses)
return self.swiftTransaction.context.fetchAll(from, fetchClauses)
}
/**
@@ -124,10 +124,10 @@ public extension CSBaseDataTransaction {
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(),
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.bridgeToSwift.context
return self.swiftTransaction.context
.fetchCount(from, fetchClauses)
.flatMap { NSNumber(value: $0) }
}
@@ -143,10 +143,10 @@ public extension CSBaseDataTransaction {
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(),
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.bridgeToSwift.context.fetchObjectID(from, fetchClauses)
return self.swiftTransaction.context.fetchObjectID(from, fetchClauses)
}
/**
@@ -163,10 +163,10 @@ public extension CSBaseDataTransaction {
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(),
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.bridgeToSwift.context.queryValue(from, selectClause, queryClauses)
return self.swiftTransaction.context.queryValue(from, selectClause, queryClauses)
}
/**
@@ -183,9 +183,9 @@ public extension CSBaseDataTransaction {
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(),
self.swiftTransaction.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.bridgeToSwift.context.queryAttributes(from, selectClause, queryClauses)
return self.swiftTransaction.context.queryAttributes(from, selectClause, queryClauses)
}
}

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `BaseDataTransaction`
*/
@objc
public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
public class CSBaseDataTransaction: NSObject {
// MARK: Object management
@@ -45,7 +45,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public var hasChanges: Bool {
return self.bridgeToSwift.hasChanges
return self.swiftTransaction.hasChanges
}
/**
@@ -57,7 +57,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func createInto(_ into: CSInto) -> Any {
return self.bridgeToSwift.create(into.bridgeToSwift)
return self.swiftTransaction.create(into.bridgeToSwift)
}
/**
@@ -69,7 +69,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func editObject(_ object: NSManagedObject?) -> Any? {
return self.bridgeToSwift.edit(object)
return self.swiftTransaction.edit(object)
}
/**
@@ -82,7 +82,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
return self.swiftTransaction.edit(into.bridgeToSwift, objectID)
}
/**
@@ -93,7 +93,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func deleteObject(_ object: NSManagedObject?) {
self.bridgeToSwift.delete(object)
self.swiftTransaction.delete(object)
}
/**
@@ -104,7 +104,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func deleteObjects(_ objects: [NSManagedObject]) {
self.bridgeToSwift.delete(objects)
self.swiftTransaction.delete(objects)
}
/**
@@ -113,23 +113,12 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func refreshAndMergeAllObjects() {
self.bridgeToSwift.refreshAndMergeAllObjects()
self.swiftTransaction.refreshAndMergeAllObjects()
}
// MARK: Inspecting Pending Objects
/**
Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObject`s that were inserted to the transaction.
*/
@objc
public func insertedObjects() -> Set<NSManagedObject> {
return self.bridgeToSwift.insertedObjects()
}
/**
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
@@ -139,7 +128,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.bridgeToSwift.insertedObjects(entity)
return self.swiftTransaction.insertedObjects(entity)
}
/**
@@ -150,7 +139,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.insertedObjectIDs()
return self.swiftTransaction.insertedObjectIDs()
}
/**
@@ -162,18 +151,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.bridgeToSwift.insertedObjectIDs(entity)
}
/**
Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObject`s that were updated to the transaction.
*/
@objc
public func updatedObjects() -> Set<NSManagedObject> {
return self.bridgeToSwift.updatedObjects()
return self.swiftTransaction.insertedObjectIDs(entity)
}
/**
@@ -185,7 +163,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.bridgeToSwift.updatedObjects(entity)
return self.swiftTransaction.updatedObjects(entity)
}
/**
@@ -196,7 +174,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.updatedObjectIDs()
return self.swiftTransaction.updatedObjectIDs()
}
/**
@@ -208,18 +186,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.bridgeToSwift.updatedObjectIDs(entity)
}
/**
Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObject`s that were deleted from the transaction.
*/
@objc
public func deletedObjects() -> Set<NSManagedObject> {
return self.bridgeToSwift.deletedObjects()
return self.swiftTransaction.updatedObjectIDs(entity)
}
/**
@@ -231,19 +198,18 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.bridgeToSwift.deletedObjects(entity)
return self.swiftTransaction.deletedObjects(entity)
}
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
@objc
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.deletedObjectIDs()
return self.swiftTransaction.deletedObjectIDs()
}
/**
@@ -255,7 +221,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
@objc
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.bridgeToSwift.deletedObjectIDs(entity)
return self.swiftTransaction.deletedObjectIDs(entity)
}
@@ -263,7 +229,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
public override var hash: Int {
return ObjectIdentifier(self.bridgeToSwift).hashValue
return ObjectIdentifier(self.swiftTransaction).hashValue
}
public override func isEqual(_ object: Any?) -> Bool {
@@ -272,25 +238,41 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
return false
}
return self.bridgeToSwift === object.bridgeToSwift
return self.swiftTransaction === object.swiftTransaction
}
// MARK: CoreStoreObjectiveCType
// MARK: Internal
public required init(_ swiftValue: BaseDataTransaction) {
internal let swiftTransaction: BaseDataTransaction
internal init(_ swiftValue: BaseDataTransaction) {
self.swiftTransaction = swiftValue
super.init()
}
public var bridgeToSwift: BaseDataTransaction {
// MARK: Deprecated
@available(*, deprecated, message: "Use -[insertedObjectsOfType:] and pass the specific entity class")
@objc
public func insertedObjects() -> Set<NSManagedObject> {
return self.swiftTransaction
return self.swiftTransaction.insertedObjects()
}
@available(*, deprecated, message: "Use -[updatedObjectsOfType:] and pass the specific entity class")
@objc
public func updatedObjects() -> Set<NSManagedObject> {
return self.swiftTransaction.updatedObjects()
}
// MARK: Private
private let swiftTransaction: BaseDataTransaction
@available(*, deprecated, message: "Use -[deletedObjectsOfType:] and pass the specific entity class")
@objc
public func deletedObjects() -> Set<NSManagedObject> {
return self.swiftTransaction.deletedObjects()
}
}

View File

@@ -129,23 +129,14 @@ public extension CSCoreStore {
// 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.")
@available(*, deprecated, 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.")
@available(*, deprecated, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public static func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {

View File

@@ -95,12 +95,6 @@ public extension CSCoreStore {
// 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

View File

@@ -135,12 +135,6 @@ public extension CSDataStack {
// 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

View File

@@ -49,41 +49,22 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
/**
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter xcodeModelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter 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: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init(
DataStack(
modelName: modelName ?? DataStack.applicationName,
xcodeModelName: xcodeModelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
/**
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@objc
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionTree: [String: String]?) {
self.init(
DataStack(
modelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
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.
*/
@@ -227,13 +208,20 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
// 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.")
@available(*, deprecated, message: "Use the -[initWithXcodeModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init(
DataStack(
xcodeModelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
@@ -245,13 +233,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
)
}
/**
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.")
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionTree:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
@@ -263,22 +245,14 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
)
}
/**
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.")
@available(*, deprecated, 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.")
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {

View File

@@ -82,6 +82,7 @@ public final class CSFrom: NSObject {
MyPersonEntity *people = [transaction fetchAllFrom:
CSFromClass([MyPersonEntity class], @"Config1")];
```
- parameter entityClass: the associated `NSManagedObject` entity class
- parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
*/
@objc
@@ -107,7 +108,7 @@ public final class CSFrom: NSObject {
CSFromClass([MyPersonEntity class],
@[[NSNull null], @"Config1"])];
```
- parameter entity: the associated `NSManagedObject` entity class
- parameter entityClass: the associated `NSManagedObject` entity class
- parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
*/
@objc
@@ -144,7 +145,7 @@ public final class CSFrom: NSObject {
public let bridgeToSwift: From<NSManagedObject>
public init<T: NSManagedObject>(_ swiftValue: From<T>) {
public init<D: NSManagedObject>(_ swiftValue: From<D>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -154,7 +155,7 @@ public final class CSFrom: NSObject {
// MARK: - From
extension From where T: NSManagedObject {
extension From where D: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -35,13 +35,13 @@ import CoreData
- SeeAlso: `GroupBy`
*/
@objc
public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
public final class CSGroupBy: NSObject, CSQueryClause {
/**
The list of key path strings to group results with
*/
@objc
public var keyPaths: [KeyPath] {
public var keyPaths: [KeyPathString] {
return self.bridgeToSwift.keyPaths
}
@@ -52,7 +52,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
- parameter keyPath: a key path string to group results with
*/
@objc
public convenience init(keyPath: KeyPath) {
public convenience init(keyPath: KeyPathString) {
self.init(GroupBy(keyPath))
}
@@ -63,7 +63,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
- parameter keyPaths: a list of key path strings to group results with
*/
@objc
public convenience init(keyPaths: [KeyPath]) {
public convenience init(keyPaths: [KeyPathString]) {
self.init(GroupBy(keyPaths))
}
@@ -102,11 +102,11 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: GroupBy
public let bridgeToSwift: GroupBy<NSManagedObject>
public init(_ swiftValue: GroupBy) {
public init<D: NSManagedObject>(_ swiftValue: GroupBy<D>) {
self.bridgeToSwift = swiftValue
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -114,7 +114,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
// MARK: - GroupBy
extension GroupBy: CoreStoreSwiftType {
extension GroupBy where D: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -122,4 +122,12 @@ extension GroupBy: CoreStoreSwiftType {
return CSGroupBy(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> GroupBy<NSManagedObject> {
return GroupBy<NSManagedObject>(self.keyPaths)
}
}

View File

@@ -112,7 +112,7 @@ public final class CSInto: NSObject {
public let bridgeToSwift: Into<NSManagedObject>
public required init<T: NSManagedObject>(_ swiftValue: Into<T>) {
public required init<D: NSManagedObject>(_ swiftValue: Into<D>) {
self.bridgeToSwift = swiftValue.downcast()
super.init()
@@ -122,7 +122,7 @@ public final class CSInto: NSObject {
// MARK: - Into
extension Into where T: NSManagedObject {
extension Into where D: NSManagedObject {
// MARK: CoreStoreSwiftType

View File

@@ -560,7 +560,6 @@ extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
fileprivate func downcast() -> ListMonitor<NSManagedObject> {
@inline(__always)
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
return unsafeBitCast(x, to: type)

View File

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

View File

@@ -152,7 +152,6 @@ extension ObjectMonitor where ObjectMonitor.ObjectType: NSManagedObject {
fileprivate func downcast() -> ObjectMonitor<NSManagedObject> {
@inline(__always)
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
return unsafeBitCast(x, to: type)

View File

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

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `OrderBy`
*/
@objc
public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause, CoreStoreObjectiveCType {
public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause {
/**
The list of sort descriptors
@@ -110,11 +110,11 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: OrderBy
public let bridgeToSwift: OrderBy<NSManagedObject>
public init(_ swiftValue: OrderBy) {
public init<D: NSManagedObject>(_ swiftValue: OrderBy<D>) {
self.bridgeToSwift = swiftValue
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -122,7 +122,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
// MARK: - OrderBy
extension OrderBy: CoreStoreSwiftType {
extension OrderBy where D: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -130,4 +130,12 @@ extension OrderBy: CoreStoreSwiftType {
return CSOrderBy(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> OrderBy<NSManagedObject> {
return OrderBy<NSManagedObject>(self.sortDescriptors)
}
}

View File

@@ -78,7 +78,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
}
/**
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]`.
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
- 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.
*/
@@ -151,11 +151,11 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
*/
@objc
public func eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
public func cs_eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
return bridge(error) {
try self.bridgeToSwift.eraseStorageAndWait(metadata: metadata as! [String: Any], soureModelHint: soureModelHint)
try self.bridgeToSwift.cs_eraseStorageAndWait(metadata: metadata as! [String: Any], soureModelHint: soureModelHint)
}
}
@@ -193,52 +193,20 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
}
// MARK: Deprecated
// MARK: Obsoleted
/**
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.")
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileURL:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
fatalError()
}
/**
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.")
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileName:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
fatalError()
}
}

View File

@@ -29,36 +29,22 @@ import CoreData
// MARK: - CSSaveResult
/**
The `CSSaveResult` serves as the Objective-C bridging type for `SaveResult`.
- SeeAlso: `SaveResult`
*/
@available(*, deprecated, message: "Use APIs that report failures with `CSError`s instead.")
@objc
public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
/**
`YES` if the `commit` operation for the transaction succeeded, either because the save succeeded or because there were no changes to save. Returns `NO` to indicate failure.
*/
@objc
public var isSuccess: Bool {
return self.bridgeToSwift.boolValue
}
/**
`YES` if the `commit` operation for the transaction failed, or `NO` otherwise. When `YES`, the `error` property returns the actual `NSError` for the failure.
*/
@objc
public var isFailure: Bool {
return !self.bridgeToSwift.boolValue
}
/**
`YES` if the `commit` operation for the transaction succeeded and if there was an actual change made. Returns `NO` otherwise.
*/
@objc
public var hasChanges: Bool {
@@ -69,9 +55,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
return hasChanges
}
/**
The `NSError` for a failed `commit` operation, or `nil` if the `commit` succeeded
*/
@objc
public var error: NSError? {
@@ -82,14 +65,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
return error.bridgeToObjectiveC
}
/**
If the result was a success, the `success` block is executed with a `BOOL` argument that indicates if there were any changes made. If the result was a failure, the `failure` block is executed with an `NSError` argument pertaining to the actual error.
The blocks are executed immediately as `@noescape` and will not be retained.
- parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made.
- parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
*/
@objc
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void, failure: (_ error: NSError) -> Void) {
@@ -103,13 +78,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
}
}
/**
If the result was a success, the `success` block is executed with a `BOOL` argument that indicates if there were any changes made. If the result was a failure, this method does nothing.
The block is executed immediately as `@noescape` and will not be retained.
- parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made.
*/
@objc
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void) {
@@ -120,13 +88,6 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
success(hasChanges)
}
/**
If the result was a failure, the `failure` block is executed with an `NSError` argument pertaining to the actual error. If the result was a success, this method does nothing.
The block is executed immediately as `@noescape` and will not be retained.
- parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
*/
@objc
public func handleFailure(_ failure: (_ error: NSError) -> Void) {

View File

@@ -36,7 +36,7 @@ import CoreData
*/
@available(OSX 10.12, *)
@objc
public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
public final class CSSectionBy: NSObject {
/**
Initializes a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
@@ -45,9 +45,9 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
*/
@objc
public static func keyPath(_ sectionKeyPath: KeyPath) -> CSSectionBy {
public static func keyPath(_ sectionKeyPath: KeyPathString) -> CSSectionBy {
return self.init(SectionBy(sectionKeyPath))
return self.init(SectionBy<NSManagedObject>(sectionKeyPath))
}
/**
@@ -58,9 +58,9 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
*/
@objc
public static func keyPath(_ sectionKeyPath: KeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
public static func keyPath(_ sectionKeyPath: KeyPathString, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer))
return self.init(SectionBy<NSManagedObject>(sectionKeyPath, sectionIndexTransformer))
}
@@ -74,11 +74,11 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: SectionBy
public let bridgeToSwift: SectionBy<NSManagedObject>
public init(_ swiftValue: SectionBy) {
public init<D>(_ swiftValue: SectionBy<D>) {
self.bridgeToSwift = swiftValue
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -87,7 +87,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
// MARK: - SectionBy
@available(OSX 10.12, *)
extension SectionBy: CoreStoreSwiftType {
extension SectionBy {
// MARK: CoreStoreSwiftType
@@ -95,4 +95,12 @@ extension SectionBy: CoreStoreSwiftType {
return CSSectionBy(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> SectionBy<NSManagedObject> {
return SectionBy<NSManagedObject>(self.sectionKeyPath, self.sectionIndexTransformer)
}
}

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `SelectTerm`
*/
@objc
public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
public final class CSSelectTerm: NSObject {
/**
Provides a `CSSelectTerm` to a `CSSelect` clause for querying an entity attribute.
@@ -48,7 +48,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
- parameter keyPath: the attribute name
*/
@objc
public convenience init(keyPath: KeyPath) {
public convenience init(keyPath: KeyPathString) {
self.init(.attribute(keyPath))
}
@@ -65,7 +65,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute
*/
@objc
public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
public static func average(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
return self.init(.average(keyPath, as: alias))
}
@@ -82,7 +82,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
- returns: a `SelectTerm` to a `Select` clause for a count query
*/
@objc
public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
public static func count(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
return self.init(.count(keyPath, as: alias))
}
@@ -99,7 +99,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute
*/
@objc
public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
public static func maximum(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
return self.init(.maximum(keyPath, as: alias))
}
@@ -116,7 +116,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute
*/
@objc
public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
public static func minimum(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
return self.init(.minimum(keyPath, as: alias))
}
@@ -133,7 +133,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute
*/
@objc
public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
public static func sum(_ keyPath: KeyPathString, as alias: KeyPathString?) -> CSSelectTerm {
return self.init(.sum(keyPath, as: alias))
}
@@ -146,12 +146,11 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]]
fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
```
- parameter keyPath: the attribute name
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used
- returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
*/
@objc
public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm {
public static func objectIDAs(_ alias: KeyPathString? = nil) -> CSSelectTerm {
return self.init(.objectID(as: alias))
}
@@ -176,11 +175,11 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: SelectTerm
public let bridgeToSwift: SelectTerm<NSManagedObject>
public init(_ swiftValue: SelectTerm) {
public init<D: NSManagedObject>(_ swiftValue: SelectTerm<D>) {
self.bridgeToSwift = swiftValue
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -188,7 +187,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
// MARK: - SelectTerm
extension SelectTerm: CoreStoreSwiftType {
extension SelectTerm where D: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -196,6 +195,24 @@ extension SelectTerm: CoreStoreSwiftType {
return CSSelectTerm(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> SelectTerm<NSManagedObject> {
switch self {
case ._attribute(let keyPath):
return SelectTerm<NSManagedObject>._attribute(keyPath)
case ._aggregate(let function, let keyPath, let alias, let nativeType):
return SelectTerm<NSManagedObject>._aggregate(function: function, keyPath: keyPath, alias: alias, nativeType: nativeType)
case ._identity(let alias, let nativeType):
return SelectTerm<NSManagedObject>._identity(alias: alias, nativeType: nativeType)
}
}
}
@@ -217,11 +234,12 @@ public final class CSSelect: NSObject {
select:CSSelectNumber(CSAggregateMax(@"age"))
// ...
```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter numberTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/
@objc
public convenience init(numberTerm: CSSelectTerm) {
self.init(Select<NSNumber>(numberTerm.bridgeToSwift))
self.init(Select<NSManagedObject, NSNumber>(numberTerm.bridgeToSwift))
}
/**
@@ -232,11 +250,12 @@ public final class CSSelect: NSObject {
select:CSSelectDecimal(CSAggregateAverage(@"price"))
// ...
```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter decimalTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/
@objc
public convenience init(decimalTerm: CSSelectTerm) {
self.init(Select<NSDecimalNumber>(decimalTerm.bridgeToSwift))
self.init(Select<NSManagedObject, NSDecimalNumber>(decimalTerm.bridgeToSwift))
}
/**
@@ -247,11 +266,12 @@ public final class CSSelect: NSObject {
select:CSSelectString(CSAttribute(@"fullname"))
// ...
```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter stringTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/
@objc
public convenience init(stringTerm: CSSelectTerm) {
self.init(Select<NSString>(stringTerm.bridgeToSwift))
self.init(Select<NSManagedObject, NSString>(stringTerm.bridgeToSwift))
}
/**
@@ -262,11 +282,12 @@ public final class CSSelect: NSObject {
select:CSSelectDate(CSAggregateMax(@"updatedDate"))
// ...
```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter dateTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/
@objc
public convenience init(dateTerm: CSSelectTerm) {
self.init(Select<Date>(dateTerm.bridgeToSwift))
self.init(Select<NSManagedObject, Date>(dateTerm.bridgeToSwift))
}
/**
@@ -277,11 +298,12 @@ public final class CSSelect: NSObject {
select:CSSelectData(CSAttribute(@"imageData"))
// ...
```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter dataTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/
@objc
public convenience init(dataTerm: CSSelectTerm) {
self.init(Select<Data>(dataTerm.bridgeToSwift))
self.init(Select<NSManagedObject, Data>(dataTerm.bridgeToSwift))
}
/**
@@ -292,11 +314,11 @@ public final class CSSelect: NSObject {
select:CSSelectObjectID()
// ...
```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/
@objc
public convenience init(objectIDTerm: ()) {
self.init(Select<NSManagedObjectID>(.objectID()))
self.init(Select<NSManagedObject, NSManagedObjectID>(.objectID()))
}
/**
@@ -309,9 +331,10 @@ public final class CSSelect: NSObject {
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- returns: a `CSSelect` clause for querying an entity attribute
*/
@objc
public static func dictionaryForTerm(_ term: CSSelectTerm) -> CSSelect {
return self.init(Select<NSDictionary>(term.bridgeToSwift))
return self.init(Select<NSManagedObject, NSDictionary>(term.bridgeToSwift))
}
/**
@@ -327,9 +350,10 @@ public final class CSSelect: NSObject {
- parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query
- returns: a `CSSelect` clause for querying an entity attribute
*/
@objc
public static func dictionaryForTerms(_ terms: [CSSelectTerm]) -> CSSelect {
return self.init(Select<NSDictionary>(terms.map { $0.bridgeToSwift }))
return self.init(Select<NSManagedObject, NSDictionary>(terms.map { $0.bridgeToSwift }))
}
@@ -359,18 +383,18 @@ public final class CSSelect: NSObject {
// MARK: CoreStoreObjectiveCType
public init<T: QueryableAttributeType>(_ swiftValue: Select<T>) {
public init<D: NSManagedObject, T: QueryableAttributeType>(_ swiftValue: Select<D, T>) {
self.attributeType = T.cs_rawAttributeType
self.selectTerms = swiftValue.selectTerms
self.selectTerms = swiftValue.selectTerms.map({ $0.downcast() })
self.bridgeToSwift = swiftValue
super.init()
}
public init<T: SelectResultType>(_ swiftValue: Select<T>) {
public init<D: NSManagedObject, T>(_ swiftValue: Select<D, T>) {
self.attributeType = .undefinedAttributeType
self.selectTerms = swiftValue.selectTerms
self.selectTerms = swiftValue.selectTerms.map({ $0.downcast() })
self.bridgeToSwift = swiftValue
super.init()
}
@@ -379,7 +403,95 @@ public final class CSSelect: NSObject {
// MARK: Internal
internal let attributeType: NSAttributeType
internal let selectTerms: [SelectTerm]
internal let selectTerms: [SelectTerm<NSManagedObject>]
// MARK: Internal
internal func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
fetchRequest.includesPendingChanges = false
fetchRequest.resultType = .dictionaryResultType
func attributeDescription(for keyPath: String, in entity: NSEntityDescription) -> NSAttributeDescription? {
let components = keyPath.components(separatedBy: ".")
switch components.count {
case 0:
return nil
case 1:
return entity.attributesByName[components[0]]
default:
guard let relationship = entity.relationshipsByName[components[0]],
let destinationEntity = relationship.destinationEntity else {
return nil
}
return attributeDescription(
for: components.dropFirst().joined(separator: "."),
in: destinationEntity
)
}
}
var propertiesToFetch = [Any]()
for term in self.selectTerms {
switch term {
case ._attribute(let keyPath):
propertiesToFetch.append(keyPath)
case ._aggregate(let function, let keyPath, let alias, let nativeType):
let entityDescription = fetchRequest.entity!
if let attributeDescription = attributeDescription(for: keyPath, in: entityDescription) {
let expressionDescription = NSExpressionDescription()
expressionDescription.name = alias
if nativeType == .undefinedAttributeType {
expressionDescription.expressionResultType = attributeDescription.attributeType
}
else {
expressionDescription.expressionResultType = nativeType
}
expressionDescription.expression = NSExpression(
forFunction: function,
arguments: [NSExpression(forKeyPath: keyPath)]
)
propertiesToFetch.append(expressionDescription)
}
else {
CoreStore.log(
.warning,
message: "The key path \"\(keyPath)\" could not be resolved in entity \(cs_typeName(entityDescription.managedObjectClassName)) as an attribute and will be ignored by \(cs_typeName(self)) query clause."
)
}
case ._identity(let alias, let nativeType):
let expressionDescription = NSExpressionDescription()
expressionDescription.name = alias
if nativeType == .undefinedAttributeType {
expressionDescription.expressionResultType = .objectIDAttributeType
}
else {
expressionDescription.expressionResultType = nativeType
}
expressionDescription.expression = NSExpression.expressionForEvaluatedObject()
propertiesToFetch.append(expressionDescription)
}
}
fetchRequest.propertiesToFetch = propertiesToFetch
}
// MARK: Private
@@ -390,7 +502,7 @@ public final class CSSelect: NSObject {
// MARK: - Select
extension Select: CoreStoreSwiftType {
extension Select where D: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -398,4 +510,12 @@ extension Select: CoreStoreSwiftType {
return CSSelect(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> Select<NSManagedObject, T> {
return Select<NSManagedObject, T>(self.selectTerms.map({ $0.downcast() }))
}
}

View File

@@ -152,7 +152,7 @@ public final class CSSetupResult: NSObject {
// MARK: CoreStoreObjectiveCType
public required init<T: StorageInterface>(_ swiftValue: SetupResult<T>) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface {
public required init<T>(_ swiftValue: SetupResult<T>) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface {
switch swiftValue {

View File

@@ -121,5 +121,5 @@ public protocol CSLocalStorage: CSStorageInterface {
Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (SQLite stores for example, can convert WAL journaling mode to DELETE before deleting)
*/
@objc
func eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool
func cs_eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool
}

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `SynchronousDataTransaction`
*/
@objc
public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
public final class CSSynchronousDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
/**
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWaitWithError:` method was already called once.
@@ -129,9 +129,9 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
public typealias SwiftType = SynchronousDataTransaction
public override var bridgeToSwift: SynchronousDataTransaction {
public var bridgeToSwift: SynchronousDataTransaction {
return super.bridgeToSwift as! SynchronousDataTransaction
return super.swiftTransaction as! SynchronousDataTransaction
}
public required init(_ swiftValue: SynchronousDataTransaction) {
@@ -139,19 +139,14 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
super.init(swiftValue as BaseDataTransaction)
}
public required init(_ swiftValue: BaseDataTransaction) {
public required override init(_ swiftValue: BaseDataTransaction) {
super.init(swiftValue as! SynchronousDataTransaction)
super.init(swiftValue)
}
// 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 {
@@ -162,12 +157,6 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
}
}
/**
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

View File

@@ -1,5 +1,5 @@
//
// CSLegacyXcodeDataModelSchema.swift
// CSUnsafeDataModelSchema.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
@@ -27,20 +27,26 @@ import CoreData
import Foundation
// MARK: - CSLegacyXcodeDataModelSchema
// MARK: - CSUnsafeDataModelSchema
/**
The `CSLegacyXcodeDataModelSchema` serves as the Objective-C bridging type for `LegacyXcodeDataModelSchema`.
The `CSUnsafeDataModelSchema` serves as the Objective-C bridging type for `UnsafeDataModelSchema`.
- SeeAlso: `LegacyXcodeDataModelSchema`
- SeeAlso: `UnsafeDataModelSchema`
*/
@objc
public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
public final class CSUnsafeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
/**
Initializes a `CSUnsafeDataModelSchema` from an `NSManagedObjectModel`.
- parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension)
- parameter model: the `NSManagedObjectModel`
*/
@objc
public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
self.bridgeToSwift = LegacyXcodeDataModelSchema(
self.bridgeToSwift = UnsafeDataModelSchema(
modelName: modelName,
model: model
)
@@ -56,7 +62,7 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSLegacyXcodeDataModelSchema else {
guard let object = object as? CSUnsafeDataModelSchema else {
return false
}
@@ -86,9 +92,9 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: LegacyXcodeDataModelSchema
public let bridgeToSwift: UnsafeDataModelSchema
public required init(_ swiftValue: LegacyXcodeDataModelSchema) {
public required init(_ swiftValue: UnsafeDataModelSchema) {
self.bridgeToSwift = swiftValue
super.init()
@@ -96,14 +102,14 @@ public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, Core
}
// MARK: - LegacyXcodeDataModelSchema
// MARK: - UnsafeDataModelSchema
extension LegacyXcodeDataModelSchema: CoreStoreSwiftType {
extension UnsafeDataModelSchema: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSLegacyXcodeDataModelSchema {
public var bridgeToObjectiveC: CSUnsafeDataModelSchema {
return CSLegacyXcodeDataModelSchema(self)
return CSUnsafeDataModelSchema(self)
}
}

View File

@@ -35,17 +35,22 @@ import CoreData
- SeeAlso: `UnsafeDataTransaction`
*/
@objc
public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
public final class CSUnsafeDataTransaction: CSBaseDataTransaction, CoreStoreObjectiveCType {
/**
Saves the transaction changes asynchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
- parameter completion: the block executed after the save completes. Success or failure is reported by the `error` argument of the block.
- parameter success: the block executed if the save succeeds.
- parameter failure: the block executed if the save fails. A `CSError` is reported as the argument of the block.
*/
@objc
public func commitWithSuccess(_ success: (() -> Void)?, _ failure: ((CSError) -> Void)?) {
self.bridgeToSwift.context.saveAsynchronouslyWithCompletion { (_, error) in
defer {
withExtendedLifetime(self, {})
}
if let error = error {
failure?(error.bridgeToObjectiveC)
@@ -54,7 +59,6 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
success?()
}
withExtendedLifetime(self, {})
}
}
@@ -118,7 +122,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
Flushes all pending changes to the transaction's observers at the end of the `closure`'s execution. This is useful in conjunction with `ListMonitor`s and `ObjectMonitor`s created from `UnsafeDataTransaction`s used to manage temporary "scratch" data.
- Important: Note that unlike `commit()`, `flush()` does not propagate/save updates to the `DataStack` and the persistent store. However, the flushed changes will be seen by children transactions created further from the current transaction (i.e. through `transaction.beginUnsafe()`)
- parameter closure: the closure where changes can be made prior to the flush
- parameter block: the block where changes can be made prior to the flush
*/
@objc
public func flush(_ block: () -> Void) {
@@ -185,9 +189,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
public typealias SwiftType = UnsafeDataTransaction
public override var bridgeToSwift: UnsafeDataTransaction {
public var bridgeToSwift: UnsafeDataTransaction {
return super.bridgeToSwift as! UnsafeDataTransaction
return super.swiftTransaction as! UnsafeDataTransaction
}
public required init(_ swiftValue: UnsafeDataTransaction) {
@@ -195,9 +199,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
super.init(swiftValue as BaseDataTransaction)
}
public required init(_ swiftValue: BaseDataTransaction) {
public required override init(_ swiftValue: BaseDataTransaction) {
super.init(swiftValue as! UnsafeDataTransaction)
super.init(swiftValue)
}
@@ -210,17 +214,16 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
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
defer {
withExtendedLifetime(self, {})
}
if let error = error {
completion?(SaveResult(error).bridgeToObjectiveC)
@@ -229,15 +232,9 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
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 {

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `Where`
*/
@objc
public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause, CoreStoreObjectiveCType {
public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClause {
/**
The internal `NSPredicate` instance for the `Where` clause
@@ -85,7 +85,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
- parameter value: the arguments for the `==` operator
*/
@objc
public convenience init(keyPath: KeyPath, isEqualTo value: CoreDataNativeType?) {
public convenience init(keyPath: KeyPathString, isEqualTo value: CoreDataNativeType?) {
self.init(value == nil || value is NSNull
? Where("\(keyPath) == nil")
@@ -99,7 +99,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
- parameter list: the array to check membership of
*/
@objc
public convenience init(keyPath: KeyPath, isMemberOf list: [CoreDataNativeType]) {
public convenience init(keyPath: KeyPathString, isMemberOf list: [CoreDataNativeType]) {
self.init(Where("\(keyPath) IN %@", list as NSArray))
}
@@ -149,11 +149,11 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: Where
public let bridgeToSwift: Where<NSManagedObject>
public init(_ swiftValue: Where) {
public init<D: NSManagedObject>(_ swiftValue: Where<D>) {
self.bridgeToSwift = swiftValue
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -161,7 +161,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
// MARK: - Where
extension Where: CoreStoreSwiftType {
extension Where where D: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -169,4 +169,12 @@ extension Where: CoreStoreSwiftType {
return CSWhere(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> Where<NSManagedObject> {
return Where<NSManagedObject>(self.predicate)
}
}

View File

@@ -37,6 +37,12 @@ import Foundation
@objc
public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
/**
Initializes an `CSXcodeDataModelSchema` from an *.xcdatamodeld file URL.
- parameter modelName: the model version, typically the file name of an *.xcdatamodeld file (without the file extension)
- parameter modelVersionFileURL: the file URL that points to the .xcdatamodeld's "momd" file.
*/
@objc
public required init(modelName: ModelVersion, modelVersionFileURL: URL) {

View File

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

View File

@@ -231,7 +231,9 @@ extension Entity: CustomDebugStringConvertible, CoreStoreDebugStringConvertible
return createFormattedString(
"(", ")",
("type", self.type),
("entityName", self.entityName)
("entityName", self.entityName),
("isAbstract", self.isAbstract),
("versionHashModifier", self.versionHashModifier as Any)
)
}
}
@@ -372,9 +374,9 @@ extension Into: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
}
// MARK: - LegacyXcodeDataModelSchema
// MARK: - UnsafeDataModelSchema
extension LegacyXcodeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
extension UnsafeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
@@ -866,7 +868,8 @@ extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvert
("storeOptions", self.storeOptions as Any),
("fileURL", self.fileURL),
("migrationMappingProviders", self.migrationMappingProviders),
("localStorageOptions", self.localStorageOptions)
("localStorageOptions", self.localStorageOptions),
("fileSize", self.fileSize() as Any)
)
}
}
@@ -983,7 +986,7 @@ extension VersionLock: CustomStringConvertible, CustomDebugStringConvertible, Co
string.append(":]")
return string
}
for (index, keyValue) in self.hashesByEntityName.enumerated() {
for (index, keyValue) in self.hashesByEntityName.sorted(by: { $0.key < $1.key }).enumerated() {
let data = keyValue.value
let count = data.count
@@ -1090,15 +1093,6 @@ fileprivate extension String {
return String(repeating: " ", count: level * 4)
}
fileprivate func trimSwiftModuleName() -> String {
if self.hasPrefix("Swift.") {
return self.substring(from: "Swift.".endIndex)
}
return self
}
fileprivate mutating func indent(_ level: Int) {
self = self.replacingOccurrences(of: "\n", with: "\n\(String.indention(level))")
@@ -1212,6 +1206,8 @@ extension NSAttributeType: CoreStoreDebugStringConvertible {
case .binaryDataAttributeType: return ".binaryDataAttributeType"
case .transformableAttributeType: return ".transformableAttributeType"
case .objectIDAttributeType: return ".objectIDAttributeType"
case .UUIDAttributeType: return ".UUIDAttributeType"
case .URIAttributeType: return ".URIAttributeType"
}
}
}

View File

@@ -47,7 +47,7 @@ public extension CoreStore {
- parameter storage: the storage
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
*/
public static func addStorage<T: StorageInterface>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
public static func addStorage<T>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
self.defaultStack.addStorage(storage, completion: completion)
}

View File

@@ -33,113 +33,204 @@ import CoreData
public extension CoreStore {
/**
Using the `defaultStack`, creates an `ObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`.
Using the `defaultStack`, creates an `ObjectMonitor` for the specified `DynamicObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `DynamicObject`.
- parameter object: the `NSManagedObject` to observe changes from
- parameter object: the `DynamicObject` to observe changes from
- returns: a `ObjectMonitor` that monitors changes to `object`
*/
public static func monitorObject<T: DynamicObject>(_ object: T) -> ObjectMonitor<T> {
public static func monitorObject<D>(_ object: D) -> ObjectMonitor<D> {
return self.defaultStack.monitorObject(object)
}
/**
Using the `defaultStack`, creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
public static func monitorList<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.defaultStack.monitorList(from, fetchClauses)
}
/**
Using the `defaultStack`, creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
public static func monitorList<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
return self.defaultStack.monitorList(from, fetchClauses)
}
/**
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let monitor = CoreStore.monitorList(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public static func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
return self.defaultStack.monitorList(clauseChain.from, clauseChain.fetchClauses)
}
/**
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public static func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
public static func monitorList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ fetchClauses: FetchClause...) {
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
}
/**
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public static func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
public static func monitorList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ fetchClauses: [FetchClause]) {
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
}
/**
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
```
CoreStore.monitorList(
{ (monitor) in
self.monitor = monitor
},
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public static func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
self.defaultStack.monitorList(
createAsynchronously: createAsynchronously,
clauseChain.from,
clauseChain.fetchClauses
)
}
/**
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
}
/**
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
}
/**
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
```
let monitor = CoreStore.monitorSectionedList(
From<MyPersonEntity>()
.sectionBy(\.age, { "\($0!) years old" })
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
*/
public static func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
return self.defaultStack.monitorSectionedList(
clauseChain.from,
clauseChain.sectionBy,
clauseChain.fetchClauses
)
}
/**
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public static func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
public static func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
}
/**
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Using the `defaultStack`, asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public static func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
public static func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
}
/**
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
```
CoreStore.monitorSectionedList(
{ (monitor) in
self.monitor = monitor
},
From<MyPersonEntity>()
.sectionBy(\.age, { "\($0!) years old" })
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
*/
public static func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
self.defaultStack.monitorSectionedList(
createAsynchronously: createAsynchronously,
clauseChain.from,
clauseChain.sectionBy,
clauseChain.fetchClauses
)
}
}

View File

@@ -32,169 +32,254 @@ import CoreData
public extension CoreStore {
/**
Using the `defaultStack`, fetches the `NSManagedObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
Using the `defaultStack`, fetches the `DynamicObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
- parameter object: a reference to the object created/fetched outside the `DataStack`
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
public static func fetchExisting<T: DynamicObject>(_ object: T) -> T? {
public static func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
return self.defaultStack.fetchExisting(object)
}
/**
Using the `defaultStack`, fetches the `NSManagedObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
Using the `defaultStack`, fetches the `DynamicObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
public static func fetchExisting<T: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
public static func fetchExisting<D: DynamicObject>(_ objectID: NSManagedObjectID) -> D? {
return self.defaultStack.fetchExisting(objectID)
}
/**
Using the `defaultStack`, fetches the `NSManagedObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
Using the `defaultStack`, fetches the `DynamicObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
- parameter objects: an array of `DynamicObject`s created/fetched outside the `DataStack`
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
*/
public static func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
public static func fetchExisting<D: DynamicObject, S: Sequence>(_ objects: S) -> [D] where S.Iterator.Element == D {
return self.defaultStack.fetchExisting(objects)
}
/**
Using the `defaultStack`, fetches the `NSManagedObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
Using the `defaultStack`, fetches the `DynamicObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
*/
public static func fetchExisting<T: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
public static func fetchExisting<D: DynamicObject, S: Sequence>(_ objectIDs: S) -> [D] where S.Iterator.Element == NSManagedObjectID {
return self.defaultStack.fetchExisting(objectIDs)
}
/**
Using the `defaultStack`, fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `defaultStack`, fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
public static func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
public static func fetchOne<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> D? {
return self.defaultStack.fetchOne(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `defaultStack`, fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
public static func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
public static func fetchOne<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> D? {
return self.defaultStack.fetchOne(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeen = CoreStore.fetchOne(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`
*/
public static func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) -> B.ObjectType? {
return self.defaultStack.fetchOne(clauseChain)
}
/**
Using the `defaultStack`, fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
public static func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
public static func fetchAll<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [D]? {
return self.defaultStack.fetchAll(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `defaultStack`, fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
public static func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
public static func fetchAll<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [D]? {
return self.defaultStack.fetchAll(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let people = CoreStore.fetchAll(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`
*/
public static func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> [B.ObjectType]? {
return self.defaultStack.fetchAll(clauseChain)
}
/**
Using the `defaultStack`, fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public static func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
public static func fetchCount<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> Int? {
return self.defaultStack.fetchCount(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `defaultStack`, fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public static func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
public static func fetchCount<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> Int? {
return self.defaultStack.fetchCount(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let numberOfAdults = CoreStore.fetchCount(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public static func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
return self.defaultStack.fetchCount(clauseChain)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
public static func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
public static func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
return self.defaultStack.fetchObjectID(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
public static func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
public static func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
return self.defaultStack.fetchObjectID(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeenID = CoreStore.fetchObjectID(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`
*/
public static func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) -> NSManagedObjectID? {
return self.defaultStack.fetchObjectID(clauseChain)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public static func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
public static func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
}
/**
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Using the `defaultStack`, fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public static func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
public static func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
}
/**
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let idsOfAdults = transaction.fetchObjectIDs(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public static func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) -> [NSManagedObjectID]? {
return self.defaultStack.fetchObjectIDs(clauseChain)
}
/**
Using the `defaultStack`, queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
@@ -205,7 +290,7 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public static func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
public static func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) -> U? {
return self.defaultStack.queryValue(from, selectClause, queryClauses)
}
@@ -220,11 +305,30 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public static func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
public static func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) -> U? {
return self.defaultStack.queryValue(from, selectClause, queryClauses)
}
/**
Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
```
let averageAdultAge = CoreStore.queryValue(
From<MyPersonEntity>()
.select(Int.self, .average(\.age))
.where(\.age > 18)
)
```
- parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request.
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
*/
public static func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType {
return self.defaultStack.queryValue(clauseChain)
}
/**
Using the `defaultStack`, queries a dictionary of attribtue values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
@@ -235,7 +339,7 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public static func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
public static func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
}
@@ -250,8 +354,36 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public static func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
public static func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
}
/**
Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
```
let results = CoreStore.queryAttributes(
From<MyPersonEntity>()
.select(
NSDictionary.self,
.attribute(\.age, as: "age"),
.count(\.age, as: "numberOfPeople")
)
.groupBy(\.age)
)
for dictionary in results! {
let age = dictionary["age"] as! Int
let count = dictionary["numberOfPeople"] as! Int
print("There are \(count) people who are \(age) years old."
}
```
- parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request.
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
*/
public static func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary {
return self.defaultStack.queryAttributes(clauseChain)
}
}

View File

@@ -143,10 +143,7 @@ public extension CoreStore {
// MARK: Deprecated
/**
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
*/
@available(*, deprecated: 3.1, message: "Use the new CoreStore.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
@available(*, deprecated, message: "Use the new CoreStore.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
public static var entityTypesByName: [EntityName: NSManagedObject.Type] {
return self.defaultStack.entityTypesByName

View File

@@ -31,10 +31,10 @@ import Foundation
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`.
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(userInfo: T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(error: CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter completion: the closure executed after the save completes. The `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)`.
- parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
*/
public static func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, completion: @escaping (AsynchronousDataTransaction.Result<T>) -> Void) {
@@ -42,11 +42,11 @@ 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 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`.
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the argument of the `success` closure. Any errors thrown from inside the `task` will be wrapped in a `CoreStoreError` and reported in the `failure` closure. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- 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)`.
- 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) {
@@ -54,7 +54,7 @@ public extension CoreStore {
}
/**
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`.
Using the `defaultStack`, performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be thrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the synchronous non-escaping closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter waitForAllObservers: When `true`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks. When `false`, this method does not wait for observers to be notified of the changes before returning. This results in lower risk for deadlocks, but the updated data may not have been propagated to the `DataStack` after returning. Defaults to `true`.
@@ -67,7 +67,7 @@ public extension CoreStore {
}
/**
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.
Using the `defaultStack`, begins a non-contiguous transaction where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
- 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.
@@ -78,7 +78,7 @@ public extension CoreStore {
}
/**
Refreshes all registered objects `NSManagedObject`s in the `defaultStack`.
Refreshes all registered objects `NSManagedObject`s or `CoreStoreObject`s in the `defaultStack`.
*/
public static func refreshAndMergeAllObjects() {
@@ -88,23 +88,12 @@ public extension CoreStore {
// 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? {

View File

@@ -43,7 +43,7 @@
#define CORESTORE_RETURNS_RETAINED __attribute__((ns_returns_retained))
#pragma mark - KeyPath Utilities
#pragma mark - KeyPathString Utilities
#define CSKeyPath(type, property) ({ \
type *_je_keypath_dummy __attribute__((unused)); \
@@ -156,7 +156,7 @@ CSFrom *_Nonnull CSFromClass(Class _Nonnull entityClass, NSArray<id> *_Nonnull c
@abstract
Initializes a <tt>CSGroupBy</tt> clause with a key path string
@param keyPaths
@param keyPath
a key path string to group results with
@result
@@ -169,7 +169,7 @@ CSGroupBy *_Nonnull CSGroupByKeyPath(NSString *_Nonnull keyPath) CORESTORE_RETUR
@abstract
Initializes a <tt>CSGroupBy</tt> clause with a list of key path strings
@param keyPaths
@param keyPath
a nil-terminated list of key path strings to group results with
@result
@@ -328,7 +328,7 @@ CSOrderBy *_Nonnull CSOrderByKey(NSSortDescriptor *_Nonnull sortDescriptor) CORE
fetchClauses:@[CSOrderByKeys(CSSortAscending(@"fullname"), CSSortDescending(@"age"), nil))]]];
@endcode
@param sortDescriptors
@param sortDescriptor
a nil-terminated array of <tt>NSSortDescriptor</tt>s
@result
@@ -473,14 +473,11 @@ CSSelect *_Nonnull CSSelectData(CSSelectTerm *_Nonnull selectTerm) CORESTORE_RET
// ...
@endcode
@param selectTerm
the <tt>CSSelectTerm</tt> specifying the attribute/aggregate value to query
@result
a <tt>CSSelect</tt> clause for querying an <tt>NSManagedObjectID</tt> value
*/
CORESTORE_EXTERN
CSSelect *_Nonnull CSSelectObjectID() CORESTORE_RETURNS_RETAINED;
CSSelect *_Nonnull CSSelectObjectID(void) CORESTORE_RETURNS_RETAINED;
#pragma mark CSTweak
@@ -538,10 +535,7 @@ CSWhere *_Nonnull CSWhereValue(BOOL value) CORESTORE_RETURNS_RETAINED;
@endcode
@param format
the format string for the predicate
@param argumentArray
the arguments for <tt>format</tt>
the format string for the predicate, followed by an optional comma-separated argument list
@result
a <tt>CSWhere</tt> clause with a predicate using the specified string format and arguments

View File

@@ -235,15 +235,15 @@ CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RE
- (void)setAffectedStores:(NSArray<NSPersistentStore *> *_Nullable)affectedStores {
// Bugfix for NSFetchRequest messing up memory management for `affectedStores`
// http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified
if (NSFoundationVersionNumber < NSFoundationVersionNumber10_0) {
if (NSFoundationVersionNumber < NSFoundationVersionNumber10_0
|| [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 11, 0, 0 }]) {
self.safeAffectedStores = affectedStores;
[super setAffectedStores:affectedStores];
return;
}
// Bugfix for NSFetchRequest messing up memory management for `affectedStores`
// http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified
if (self.releaseArray != NULL) {
CFRelease(self.releaseArray);

View File

@@ -31,7 +31,7 @@ import Foundation
/**
`CoreStoreObjectiveCType`s are Objective-C accessible classes that represent CoreStore's Swift types.
*/
public protocol CoreStoreObjectiveCType: class, AnyObject {
public protocol CoreStoreObjectiveCType: class {
/**
The corresponding Swift type

View File

@@ -294,7 +294,8 @@ public extension NSError {
}
switch CocoaError.Code(rawValue: self.code) {
case CocoaError.Code.persistentStoreIncompatibleVersionHash,
case CocoaError.Code.persistentStoreIncompatibleSchema,
CocoaError.Code.persistentStoreIncompatibleVersionHash,
CocoaError.Code.migrationMissingSourceModel,
CocoaError.Code.migration:
return true

View File

@@ -34,7 +34,7 @@ internal extension CoreStoreFetchRequest {
// MARK: Internal
@nonobjc @inline(__always)
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> {
internal func dynamicCast<U>() -> NSFetchRequest<U> {
return unsafeBitCast(self, to: NSFetchRequest<U>.self)
}

View File

@@ -35,7 +35,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
// MARK: Internal
@nonobjc
internal convenience init<T: DynamicObject>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
internal convenience init<D>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<D>, sectionBy: SectionBy<D>? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
self.init(
context: dataStack.mainContext,
@@ -47,33 +47,18 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
}
@nonobjc
internal init<T: DynamicObject>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<T>?, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
internal init<D>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<D>, sectionBy: SectionBy<D>? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
_ = from?.applyToFetchRequest(
_ = from.applyToFetchRequest(
fetchRequest,
context: context,
applyAffectedStores: false
)
applyFetchClauses(fetchRequest)
if let from = from {
self.reapplyAffectedStores = { fetchRequest, context in
self.reapplyAffectedStores = { fetchRequest, context in
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
}
}
else {
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap({ From<T>($0 as! T.Type) }) else {
CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From<T>.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
}
self.reapplyAffectedStores = { fetchRequest, context in
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
}
return from.applyAffectedStoresForFetchedRequest(fetchRequest, context: context)
}
super.init(
@@ -98,7 +83,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
}
@nonobjc
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchedResultsController<U> {
internal func dynamicCast<U>() -> NSFetchedResultsController<U> {
return unsafeBitCast(self, to: NSFetchedResultsController<U>.self)
}

View File

@@ -47,12 +47,6 @@ public enum LogLevel {
*/
public protocol CoreStoreLogger {
/**
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false` if not implemented.
*/
// TODO: test before release (rolled back)
// var enableObjectConcurrencyDebugging: Bool { get set }
/**
Handles log messages sent by the `CoreStore` framework.
@@ -100,13 +94,6 @@ public protocol CoreStoreLogger {
extension CoreStoreLogger {
// TODO: test before release (rolled back)
// public var enableObjectConcurrencyDebugging: Bool {
//
// get { return false }
// set {}
// }
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))

View File

@@ -0,0 +1,51 @@
//
// CoreStoreManagedObject.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
// MARK: - CoreStoreManagedObject
@objc internal class CoreStoreManagedObject: NSManagedObject {
internal typealias CustomGetter = @convention(block) (_ rawObject: Any) -> Any?
internal typealias CustomSetter = @convention(block) (_ rawObject: Any, _ newValue: Any?) -> Void
internal typealias CustomGetterSetter = (getter: CustomGetter?, setter: CustomSetter?)
@nonobjc @inline(__always)
internal static func cs_subclassName(for entity: DynamicEntity, in modelVersion: ModelVersion) -> String {
return "_\(NSStringFromClass(CoreStoreManagedObject.self))__\(modelVersion)__\(NSStringFromClass(entity.type))__\(entity.entityName)"
}
}
// MARK: - Private
private enum Static {
static let queue = DispatchQueue.concurrent("com.coreStore.coreStoreManagerObjectBarrierQueue")
static var cache: [ObjectIdentifier: [KeyPathString: Set<KeyPathString>]] = [:]
}

View File

@@ -27,75 +27,85 @@ import CoreData
import Foundation
// MARK: - DynamicObject
public extension DynamicObject where Self: CoreStoreObject {
public static func keyPath<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Required<V>) -> String {
return attribute(self.meta).keyPath
}
public static func keyPath<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> String {
return attribute(self.meta).keyPath
}
public static func `where`(_ condition: (Self) -> Where) -> Where {
return condition(self.meta)
}
public static func ascending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
return OrderBy(.ascending(attribute(self.meta).keyPath))
}
public static func descending<O: CoreStoreObject, V: ImportableAttributeType>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy {
return OrderBy(.descending(attribute(self.meta).keyPath))
}
}
// MARK: - ValueContainer.Required
public extension ValueContainer.Required {
@inline(__always)
public static func == (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where {
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.nickname == "John" }))
```
*/
public static func == (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
return Where(attribute.keyPath, isEqualTo: value)
}
@inline(__always)
public static func < (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where {
/**
Creates a `Where` clause by comparing if a property is not equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.nickname != "John" }))
```
*/
public static func != (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
return !Where(attribute.keyPath, isEqualTo: value)
}
/**
Creates a `Where` clause by comparing if a property is less than a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age < 20 }))
```
*/
public static func < (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
return Where("%K < %@", attribute.keyPath, value)
}
@inline(__always)
public static func > (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where {
/**
Creates a `Where` clause by comparing if a property is greater than a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age > 20 }))
```
*/
public static func > (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
return Where("%K > %@", attribute.keyPath, value)
}
@inline(__always)
public static func <= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where {
/**
Creates a `Where` clause by comparing if a property is less than or equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age <= 20 }))
```
*/
public static func <= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
return Where("%K <= %@", attribute.keyPath, value)
}
@inline(__always)
public static func >= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where {
/**
Creates a `Where` clause by comparing if a property is greater than or equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age >= 20 }))
```
*/
public static func >= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where<O> {
return Where("%K >= %@", attribute.keyPath, value)
}
@inline(__always)
public static func != (_ attribute: ValueContainer<O>.Required<V>, _ value: V) -> Where {
/**
Creates a `Where` clause by checking if a sequence contains the value of a property
```
let dog = CoreStore.fetchOne(From<Dog>().where({ ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname }))
```
*/
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Required<V>) -> Where<O> where S.Iterator.Element == V {
return !Where(attribute.keyPath, isEqualTo: value)
return Where(attribute.keyPath, isMemberOf: sequence)
}
}
@@ -104,15 +114,213 @@ public extension ValueContainer.Required {
public extension ValueContainer.Optional {
@inline(__always)
public static func == (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.nickname == "John" }))
```
*/
public static func == (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
return Where(attribute.keyPath, isEqualTo: value)
}
@inline(__always)
public static func != (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where {
/**
Creates a `Where` clause by comparing if a property is not equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.nickname != "John" }))
```
*/
public static func != (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
return !Where(attribute.keyPath, isEqualTo: value)
}
/**
Creates a `Where` clause by comparing if a property is less than a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age < 20 }))
```
*/
public static func < (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
if let value = value {
return Where("%K < %@", attribute.keyPath, value)
}
else {
return Where("%K < nil", attribute.keyPath)
}
}
/**
Creates a `Where` clause by comparing if a property is greater than a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age > 20 }))
```
*/
public static func > (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
if let value = value {
return Where("%K > %@", attribute.keyPath, value)
}
else {
return Where("%K > nil", attribute.keyPath)
}
}
/**
Creates a `Where` clause by comparing if a property is less than or equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age <= 20 }))
```
*/
public static func <= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
if let value = value {
return Where("%K <= %@", attribute.keyPath, value)
}
else {
return Where("%K <= nil", attribute.keyPath)
}
}
/**
Creates a `Where` clause by comparing if a property is greater than or equal to a value
```
let person = CoreStore.fetchOne(From<Person>().where({ $0.age >= 20 }))
```
*/
public static func >= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) -> Where<O> {
if let value = value {
return Where("%K >= %@", attribute.keyPath, value)
}
else {
return Where("%K >= nil", attribute.keyPath)
}
}
/**
Creates a `Where` clause by checking if a sequence contains the value of a property
```
let dog = CoreStore.fetchOne(From<Dog>().where({ ["Pluto", "Snoopy", "Scooby"] ~= $0.nickname }))
```
*/
public static func ~= <S: Sequence>(_ sequence: S, _ attribute: ValueContainer<O>.Optional<V>) -> Where<O> where S.Iterator.Element == V {
return Where(attribute.keyPath, isMemberOf: sequence)
}
}
// MARK: - RelationshipContainer.ToOne
public extension RelationshipContainer.ToOne {
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let dog = CoreStore.fetchOne(From<Dog>().where({ $0.master == me }))
```
*/
public static func == (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where<O> {
return Where(relationship.keyPath, isEqualTo: object)
}
/**
Creates a `Where` clause by comparing if a property is not equal to a value
```
let dog = CoreStore.fetchOne(From<Dog>().where({ $0.master != me }))
```
*/
public static func != (_ relationship: RelationshipContainer<O>.ToOne<D>, _ object: D?) -> Where<O> {
return !Where(relationship.keyPath, isEqualTo: object)
}
/**
Creates a `Where` clause by checking if a sequence contains the value of a property
```
let dog = CoreStore.fetchOne(From<Dog>().where({ [john, joe, bob] ~= $0.master }))
```
*/
public static func ~= <S: Sequence>(_ sequence: S, _ relationship: RelationshipContainer<O>.ToOne<D>) -> Where<O> where S.Iterator.Element == D {
return Where(relationship.keyPath, isMemberOf: sequence)
}
}
// MARK: Deprecated
extension DynamicObject where Self: CoreStoreObject {
@available(*, deprecated, message: "Use the String(keyPath:) initializer and pass the KeyPath: String(keyPath: \\Person.name)")
public static func keyPath<O, V>(_ attribute: (Self) -> ValueContainer<O>.Required<V>) -> String {
return attribute(self.meta).keyPath
}
@available(*, deprecated, message: "Use the String(keyPath:) initializer and pass the KeyPath: String(keyPath: \\Person.name)")
public static func keyPath<O, V>(_ attribute: (Self) -> ValueContainer<O>.Optional<V>) -> String {
return attribute(self.meta).keyPath
}
@available(*, deprecated, message: "Use the String(keyPath:) initializer and pass the KeyPath: String(keyPath: \\Person.friend)")
public static func keyPath<O, D>(_ relationship: (Self) -> RelationshipContainer<O>.ToOne<D>) -> String {
return relationship(self.meta).keyPath
}
@available(*, deprecated, message: "Use the String(keyPath:) initializer and pass the KeyPath: String(keyPath: \\Person.friends)")
public static func keyPath<O, D>(_ relationship: (Self) -> RelationshipContainer<O>.ToManyOrdered<D>) -> String {
return relationship(self.meta).keyPath
}
@available(*, deprecated, message: "Use the String(keyPath:) initializer and pass the KeyPath: String(keyPath: \\Person.friends)")
public static func keyPath<O, D>(_ relationship: (Self) -> RelationshipContainer<O>.ToManyUnordered<D>) -> String {
return relationship(self.meta).keyPath
}
@available(*, deprecated, message: "Use the Where<DynamicObject>(_:) initializer that accepts the same closure argument")
public static func `where`(_ condition: (Self) -> Where<Self>) -> Where<Self> {
return condition(self.meta)
}
@available(*, deprecated, message: "Use the new OrderBy<DynamicObject>(ascending:) overload that accepts the same closure argument")
public static func orderBy<O, V>(ascending attribute: (Self) -> ValueContainer<O>.Required<V>) -> OrderBy<Self> {
return OrderBy(.ascending(attribute(self.meta).keyPath))
}
@available(*, deprecated, message: "Use the new OrderBy<DynamicObject>(ascending:) overload that accepts the same closure argument")
public static func orderBy<O, V>(ascending attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy<Self> {
return OrderBy(.ascending(attribute(self.meta).keyPath))
}
@available(*, deprecated, message: "Use the new OrderBy<DynamicObject>(descending:) overload that accepts the same closure argument")
public static func orderBy<O, V>(descending attribute: (Self) -> ValueContainer<O>.Required<V>) -> OrderBy<Self> {
return OrderBy(.descending(attribute(self.meta).keyPath))
}
@available(*, deprecated, message: "Use the new OrderBy<DynamicObject>(descending:) overload that accepts the same closure argument")
public static func orderBy<O, V>(descending attribute: (Self) -> ValueContainer<O>.Optional<V>) -> OrderBy<Self> {
return OrderBy(.descending(attribute(self.meta).keyPath))
}
}

View File

@@ -33,13 +33,13 @@ import Foundation
The `CoreStoreObject` is an abstract class for creating CoreStore-managed objects that are more type-safe and more convenient than `NSManagedObject` subclasses. The model entities for `CoreStoreObject` subclasses are inferred from the Swift declaration themselves; no .xcdatamodeld files are needed. To declare persisted attributes and relationships for the `CoreStoreObject` subclass, declare properties of type `Value.Required<T>`, `Value.Optional<T>` for values, or `Relationship.ToOne<T>`, `Relationship.ToManyOrdered<T>`, `Relationship.ToManyUnordered<T>` for relationships.
```
class Animal: CoreStoreObject {
let species = Value.Required<String>("species")
let species = Value.Required<String>("species", initial: "")
let nickname = Value.Optional<String>("nickname")
let master = Relationship.ToOne<Person>("master")
}
class Person: CoreStoreObject {
let name = Value.Required<String>("name")
let name = Value.Required<String>("name", initial: "")
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
}
```
@@ -68,8 +68,8 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
public required init(rawObject: NSManagedObject) {
self.isMeta = false
self.rawObject = rawObject
self.initializeAttributes(Mirror(reflecting: self), { [unowned self] in self })
self.rawObject = (rawObject as! CoreStoreManagedObject)
self.initializeAttributes(Mirror(reflecting: self), self)
}
/**
@@ -110,13 +110,13 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
// MARK: Internal
internal let rawObject: NSManagedObject?
internal let rawObject: CoreStoreManagedObject?
internal let isMeta: Bool
// MARK: Private
private func initializeAttributes(_ mirror: Mirror, _ parentObject: @escaping () -> CoreStoreObject) {
private func initializeAttributes(_ mirror: Mirror, _ parentObject: CoreStoreObject) {
_ = mirror.superclassMirror.flatMap({ self.initializeAttributes($0, parentObject) })
for child in mirror.children {
@@ -135,3 +135,26 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
}
}
}
// MARK: - DynamicObject where Self: CoreStoreObject
public extension DynamicObject where Self: CoreStoreObject {
/**
Returns the `PartialObject` instance for the object, which acts as a fast, type-safe KVC interface for `CoreStoreObject`.
*/
public func partialObject() -> PartialObject<Self> {
CoreStore.assert(
!self.isMeta,
"Attempted to create a \(cs_typeName(PartialObject<Self>.self)) from a meta object. Meta objects are only used for querying keyPaths and infering types."
)
return PartialObject<Self>(self.rawObject!)
}
internal static var meta: Self {
return self.init(asMeta: ())
}
}

View File

@@ -33,13 +33,13 @@ import Foundation
The `CoreStoreSchema` describes models written for `CoreStoreObject` Swift class declarations for a particular model version. `CoreStoreObject` entities for a model version should be added to `CoreStoreSchema` instance.
```
class Animal: CoreStoreObject {
let species = Value.Required<String>("species")
let species = Value.Required<String>("species", initial: "")
let nickname = Value.Optional<String>("nickname")
let master = Relationship.ToOne<Person>("master")
}
class Person: CoreStoreObject {
let name = Value.Required<String>("name")
let name = Value.Required<String>("name", initial: "")
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
}
@@ -66,13 +66,13 @@ public final class CoreStoreSchema: DynamicSchema {
Initializes a `CoreStoreSchema`. Using this initializer only if the entities don't need to be assigned to particular "Configurations". To use multiple configurations (for example, to separate entities in different `StorageInterface`s), use the `init(modelVersion:entitiesByConfiguration:versionLock:)` initializer.
```
class Animal: CoreStoreObject {
let species = Value.Required<String>("species")
let species = Value.Required<String>("species", initial: "")
let nickname = Value.Optional<String>("nickname")
let master = Relationship.ToOne<Person>("master")
}
class Person: CoreStoreObject {
let name = Value.Required<String>("name")
let name = Value.Required<String>("name", initial: "")
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
}
@@ -112,12 +112,12 @@ public final class CoreStoreSchema: DynamicSchema {
Initializes a `CoreStoreSchema`. Using this initializer if multiple "Configurations" (for example, to separate entities in different `StorageInterface`s) are needed. To add an entity only to the default configuration, assign an empty set to its configurations list. Note that regardless of the set configurations, all entities will be added to the default configuration.
```
class Animal: CoreStoreObject {
let species = Value.Required<String>("species")
let species = Value.Required<String>("species", initial: "")
let nickname = Value.Optional<String>("nickname")
}
class Person: CoreStoreObject {
let name = Value.Required<String>("name")
let name = Value.Required<String>("name", initial: "")
}
CoreStore.defaultStack = DataStack(
@@ -187,7 +187,7 @@ public final class CoreStoreSchema: DynamicSchema {
#if DEBUG
CoreStore.log(
.notice,
message: "These are hashes for the \(cs_typeName(CoreStoreSchema.self)) with version name \"\(modelVersion)\". Copy the dictionary below and pass it to the \(cs_typeName(CoreStoreSchema.self)) initializer's \"versionLock\" argument:\n\(VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName))"
message: "These are hashes for the \(cs_typeName(CoreStoreSchema.self)) with version name \"\(modelVersion)\". Copy the dictionary below and pass it to the \(cs_typeName(CoreStoreSchema.self)) initializer's \"versionLock\" argument:\nversionLock: \(VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName))"
)
#endif
}
@@ -200,35 +200,44 @@ public final class CoreStoreSchema: DynamicSchema {
public func rawModel() -> NSManagedObjectModel {
if let cachedRawModel = self.cachedRawModel {
return CoreStoreSchema.barrierQueue.sync(flags: .barrier) {
return cachedRawModel
}
let rawModel = NSManagedObjectModel()
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
for entity in self.allEntities {
let entityDescription = self.entityDescription(
for: entity,
initializer: CoreStoreSchema.firstPassCreateEntityDescription
if let cachedRawModel = self.cachedRawModel {
return cachedRawModel
}
let rawModel = NSManagedObjectModel()
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
var allCustomGettersSetters: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]] = [:]
for entity in self.allEntities {
let (entityDescription, customGetterSetterByKeyPaths) = self.entityDescription(
for: entity,
initializer: CoreStoreSchema.firstPassCreateEntityDescription(from:in:)
)
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
allCustomGettersSetters[entity] = customGetterSetterByKeyPaths
}
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
CoreStoreSchema.fourthPassSynthesizeManagedObjectClasses(
for: entityDescriptionsByEntity,
allCustomGettersSetters: allCustomGettersSetters
)
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
}
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
CoreStoreSchema.thirdPassConnectInheritanceTree(for: entityDescriptionsByEntity)
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
for (configuration, entities) in self.entitiesByConfiguration {
rawModel.setEntities(
entities
.map({ entityDescriptionsByEntity[$0]! })
.sorted(by: { $0.name! < $1.name! }),
forConfigurationName: configuration
)
rawModel.entities = entityDescriptionsByEntity.values.sorted(by: { $0.name! < $1.name! })
for (configuration, entities) in self.entitiesByConfiguration {
rawModel.setEntities(
entities
.map({ entityDescriptionsByEntity[$0]! })
.sorted(by: { $0.name! < $1.name! }),
forConfigurationName: configuration
)
}
self.cachedRawModel = rawModel
return rawModel
}
self.cachedRawModel = rawModel
return rawModel
}
@@ -244,28 +253,33 @@ public final class CoreStoreSchema: DynamicSchema {
private let allEntities: Set<DynamicEntity>
private var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
private var customGettersSettersByEntity: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]] = [:]
private weak var cachedRawModel: NSManagedObjectModel?
private func entityDescription(for entity: DynamicEntity, initializer: (DynamicEntity) -> NSEntityDescription) -> NSEntityDescription {
private func entityDescription(for entity: DynamicEntity, initializer: (DynamicEntity, ModelVersion) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter])) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]) {
if let cachedEntityDescription = self.entityDescriptionsByEntity[entity] {
return cachedEntityDescription
return (cachedEntityDescription, self.customGettersSettersByEntity[entity] ?? [:])
}
let entityDescription = withoutActuallyEscaping(initializer, do: { $0(entity) })
let modelVersion = self.modelVersion
let (entityDescription, customGetterSetterByKeyPaths) = withoutActuallyEscaping(initializer, do: { $0(entity, modelVersion) })
self.entityDescriptionsByEntity[entity] = entityDescription
return entityDescription
self.customGettersSettersByEntity[entity] = customGetterSetterByKeyPaths
return (entityDescription, customGetterSetterByKeyPaths)
}
private static func firstPassCreateEntityDescription(from entity: DynamicEntity) -> NSEntityDescription {
private static func firstPassCreateEntityDescription(from entity: DynamicEntity, in modelVersion: ModelVersion) -> (entity: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]) {
let entityDescription = NSEntityDescription()
entityDescription.coreStoreEntity = entity
entityDescription.name = entity.entityName
entityDescription.isAbstract = entity.isAbstract
entityDescription.versionHashModifier = entity.versionHashModifier
entityDescription.managedObjectClassName = NSStringFromClass(NSManagedObject.self)
entityDescription.managedObjectClassName = CoreStoreManagedObject.cs_subclassName(for: entity, in: modelVersion)
var keyPathsByAffectedKeyPaths: [KeyPathString: Set<KeyPathString>] = [:]
var customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter] = [:]
func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] {
var propertyDescriptions: [NSPropertyDescription] = []
@@ -276,14 +290,16 @@ public final class CoreStoreSchema: DynamicSchema {
case let attribute as AttributeProtocol:
let description = NSAttributeDescription()
description.name = attribute.keyPath
description.attributeType = type(of: attribute).attributeType
description.attributeType = Swift.type(of: attribute).attributeType
description.isOptional = attribute.isOptional
description.isIndexed = attribute.isIndexed
description.defaultValue = attribute.defaultValue
description.defaultValue = attribute.defaultValue()
description.isTransient = attribute.isTransient
description.versionHashModifier = attribute.versionHashModifier
description.renamingIdentifier = attribute.renamingIdentifier
description.versionHashModifier = attribute.versionHashModifier()
description.renamingIdentifier = attribute.renamingIdentifier()
propertyDescriptions.append(description)
keyPathsByAffectedKeyPaths[attribute.keyPath] = attribute.affectedByKeyPaths()
customGetterSetterByKeyPaths[attribute.keyPath] = (attribute.getter, attribute.setter)
case let relationship as RelationshipProtocol:
let description = NSRelationshipDescription()
@@ -292,9 +308,10 @@ public final class CoreStoreSchema: DynamicSchema {
description.maxCount = relationship.maxCount
description.isOrdered = relationship.isOrdered
description.deleteRule = relationship.deleteRule
description.versionHashModifier = relationship.versionHashModifier
description.renamingIdentifier = relationship.renamingIdentifier
description.versionHashModifier = relationship.versionHashModifier()
description.renamingIdentifier = relationship.renamingIdentifier()
propertyDescriptions.append(description)
keyPathsByAffectedKeyPaths[relationship.keyPath] = relationship.affectedByKeyPaths()
default:
continue
@@ -302,9 +319,9 @@ public final class CoreStoreSchema: DynamicSchema {
}
return propertyDescriptions
}
entityDescription.properties = createProperties(for: entity.type as! CoreStoreObject.Type)
return entityDescription
entityDescription.keyPathsByAffectedKeyPaths = keyPathsByAffectedKeyPaths
return (entityDescription, customGetterSetterByKeyPaths)
}
private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) {
@@ -425,4 +442,112 @@ public final class CoreStoreSchema: DynamicSchema {
)
}
}
private static func fourthPassSynthesizeManagedObjectClasses(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription], allCustomGettersSetters: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]]) {
func createManagedObjectSubclass(for entityDescription: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]?) {
let superEntity = entityDescription.superentity
let className = entityDescription.managedObjectClassName!
guard case nil = NSClassFromString(className) as! CoreStoreManagedObject.Type? else {
return
}
if let superEntity = superEntity {
createManagedObjectSubclass(
for: superEntity,
customGetterSetterByKeyPaths: superEntity.coreStoreEntity.flatMap({ allCustomGettersSetters[$0] })
)
}
let superClass = cs_lazy { () -> CoreStoreManagedObject.Type in
if let superClassName = superEntity?.managedObjectClassName,
let superClass = NSClassFromString(superClassName) {
return superClass as! CoreStoreManagedObject.Type
}
return CoreStoreManagedObject.self
}
let managedObjectClass: AnyClass = className.withCString {
return objc_allocateClassPair(superClass, $0, 0)!
}
defer {
objc_registerClassPair(managedObjectClass)
}
func capitalize(_ string: String) -> String {
return string.replacingCharacters(
in: Range(uncheckedBounds: (string.startIndex, string.index(after: string.startIndex))),
with: String(string[string.startIndex]).uppercased()
)
}
for (attributeName, customGetterSetters) in (customGetterSetterByKeyPaths ?? [:])
where customGetterSetters.getter != nil || customGetterSetters.setter != nil {
if let getter = customGetterSetters.getter {
let getterName = "\(attributeName)"
guard class_addMethod(
managedObjectClass,
NSSelectorFromString(getterName),
imp_implementationWithBlock(getter),
"@@:") else {
CoreStore.abort("Could not dynamically add getter method \"\(getterName)\" to class \(cs_typeName(managedObjectClass))")
}
}
if let setter = customGetterSetters.setter {
let setterName = "set\(capitalize(attributeName)):"
guard class_addMethod(
managedObjectClass,
NSSelectorFromString(setterName),
imp_implementationWithBlock(setter),
"v@:@") else {
CoreStore.abort("Could not dynamically add setter method \"\(setterName)\" to class \(cs_typeName(managedObjectClass))")
}
}
}
let newSelector = NSSelectorFromString("cs_keyPathsForValuesAffectingValueForKey:")
let keyPathsByAffectedKeyPaths = entityDescription.keyPathsByAffectedKeyPaths
let keyPathsForValuesAffectingValue: @convention(block) (Any, String) -> Set<String> = { (instance, keyPath) in
if let keyPaths = keyPathsByAffectedKeyPaths[keyPath] {
return keyPaths
}
return []
}
let origSelector = #selector(NSManagedObject.keyPathsForValuesAffectingValue(forKey:))
let metaClass: AnyClass = object_getClass(managedObjectClass)!
let origMethod = class_getClassMethod(managedObjectClass, origSelector)!
let origImp = method_getImplementation(origMethod)
let newImp = imp_implementationWithBlock(keyPathsForValuesAffectingValue)
if class_addMethod(metaClass, origSelector, newImp, method_getTypeEncoding(origMethod)) {
class_replaceMethod(metaClass, newSelector, origImp, method_getTypeEncoding(origMethod))
}
else {
let newMethod = class_getClassMethod(managedObjectClass, newSelector)!
method_exchangeImplementations(origMethod, newMethod)
}
}
for (dynamicEntity, entityDescription) in entityDescriptionsByEntity {
createManagedObjectSubclass(
for: entityDescription,
customGetterSetterByKeyPaths: allCustomGettersSetters[dynamicEntity]
)
}
}
}

View File

@@ -64,3 +64,11 @@ public typealias EntityName = String
An `String` that pertains to a dynamically-accessable class name (usable with NSClassFromString(...)).
*/
public typealias ClassName = String
// MARK: - KeyPathString
/**
An `String` that pertains to a attribute keyPaths.
*/
public typealias KeyPathString = String

View File

@@ -29,11 +29,28 @@ import Foundation
// MARK: - CustomSchemaMappingProvider
open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
/**
A `SchemaMappingProvider` that accepts custom mappings for some entities. Mappings of entities with no `CustomMapping` provided will be automatically calculated if possible.
*/
public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
/**
The source model version for the mapping.
*/
public let sourceVersion: ModelVersion
/**
The destination model version for the mapping.
*/
public let destinationVersion: ModelVersion
/**
Creates a `CustomSchemaMappingProvider`
- parameter sourceVersion: the source model version for the mapping
- parameter destinationVersion: the destination model version for the mapping
- parameter entityMappings: a list of `CustomMapping`s. Mappings of entities with no `CustomMapping` provided will be automatically calculated if possible. Any conflicts or ambiguity will raise an assertion.
*/
public required init(from sourceVersion: ModelVersion, to destinationVersion: ModelVersion, entityMappings: Set<CustomMapping> = []) {
CoreStore.assert(
@@ -54,16 +71,42 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
// MARK: - CustomMapping
/**
Provides the type of mapping for an entity. Mappings of entities with no `CustomMapping` provided will be automatically calculated if possible. Any conflicts or ambiguity will raise an assertion.
*/
public enum CustomMapping: Hashable {
public typealias Transformer = (_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void
/**
The `sourceEntity` is meant to be removed from the source `DynamicSchema` and should not be migrated to the destination `DynamicSchema`.
*/
case deleteEntity(sourceEntity: EntityName)
/**
The `destinationEntity` is newly added to the destination `DynamicSchema` and has no mapping from the source `DynamicSchema`.
*/
case insertEntity(destinationEntity: EntityName)
/**
The `DynamicSchema`s entity has no changes and can be copied directly from `sourceEntity` to `destinationEntity`.
*/
case copyEntity(sourceEntity: EntityName, destinationEntity: EntityName)
/**
The `DynamicSchema`s entity needs transformations from `sourceEntity` to `destinationEntity`. The `transformer` closure will be used to apply the changes. The `CustomMapping.inferredTransformation` method can be used directly as the `transformer` if the changes can be inferred (i.e. lightweight).
*/
case transformEntity(sourceEntity: EntityName, destinationEntity: EntityName, transformer: Transformer)
static func inferredTransformation(_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void {
/**
The closure type for `CustomMapping.transformEntity`.
- parameter sourceObject: a proxy object representing the source entity. The properties can be accessed via keyPath.
- parameter createDestinationObject: the closure to create the object for the destination entity. The `CustomMapping.inferredTransformation` method can be used directly as the `transformer` if the changes can be inferred (i.e. lightweight). The object is created lazily and executing the closure multiple times will return the same instance. The destination object's properties can be accessed and updated via keyPath.
*/
public typealias Transformer = (_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void
/**
The `CustomMapping.inferredTransformation` method can be used directly as the `transformer` if the changes can be inferred (i.e. lightweight).
*/
public static func inferredTransformation(_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void {
let destinationObject = createDestinationObject()
destinationObject.enumerateAttributes { (attribute, sourceAttribute) in
@@ -75,34 +118,6 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
}
}
var entityMappingSourceEntity: EntityName? {
switch self {
case .deleteEntity(let sourceEntity),
.copyEntity(let sourceEntity, _),
.transformEntity(let sourceEntity, _, _):
return sourceEntity
case .insertEntity:
return nil
}
}
var entityMappingDestinationEntity: EntityName? {
switch self {
case .insertEntity(let destinationEntity),
.copyEntity(_, let destinationEntity),
.transformEntity(_, let destinationEntity, _):
return destinationEntity
case .deleteEntity:
return nil
}
}
// MARK: Equatable
@@ -151,29 +166,80 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
^ destinationEntity.hashValue
}
}
// MARK: FilePrivate
fileprivate var entityMappingSourceEntity: EntityName? {
switch self {
case .deleteEntity(let sourceEntity),
.copyEntity(let sourceEntity, _),
.transformEntity(let sourceEntity, _, _):
return sourceEntity
case .insertEntity:
return nil
}
}
fileprivate var entityMappingDestinationEntity: EntityName? {
switch self {
case .insertEntity(let destinationEntity),
.copyEntity(_, let destinationEntity),
.transformEntity(_, let destinationEntity, _):
return destinationEntity
case .deleteEntity:
return nil
}
}
}
// MARK: - UnsafeSourceObject
/**
The read-only proxy object used for the source object in a mapping's `Transformer` closure. Properties can be accessed either by keyPath string or by `NSAttributeDescription`.
*/
public final class UnsafeSourceObject {
public subscript(attribute: KeyPath) -> Any? {
/**
Accesses the property value via its keyPath.
*/
public subscript(attribute: KeyPathString) -> Any? {
return self.rawObject.cs_accessValueForKVCKey(attribute)
}
/**
Accesses the property value via its `NSAttributeDescription`, which can be accessed from the `enumerateAttributes(_:)` method.
*/
public subscript(attribute: NSAttributeDescription) -> Any? {
return self.rawObject.cs_accessValueForKVCKey(attribute.name)
}
/**
Enumerates the all `NSAttributeDescription`s. The `attribute` argument can be used as the subscript key to access the property.
*/
public func enumerateAttributes(_ closure: (_ attribute: NSAttributeDescription) -> Void) {
for case let attribute as NSAttributeDescription in self.rawObject.entity.properties {
func enumerate(_ entity: NSEntityDescription, _ closure: (NSAttributeDescription) -> Void) {
closure(attribute)
if let superEntity = entity.superentity {
enumerate(superEntity, closure)
}
for case let attribute as NSAttributeDescription in entity.properties {
closure(attribute)
}
}
enumerate(self.rawObject.entity, closure)
}
@@ -193,42 +259,62 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
// MARK: - UnsafeDestinationObject
/**
The read-write proxy object used for the destination object that can be created in a mapping's `Transformer` closure. Properties can be accessed and mutated either through keyPath string or by `NSAttributeDescription`.
*/
public final class UnsafeDestinationObject {
public subscript(attribute: KeyPath) -> Any? {
/**
Accesses or mutates the property value via its keyPath.
*/
public subscript(attribute: KeyPathString) -> Any? {
get { return self.rawObject.cs_accessValueForKVCKey(attribute) }
set { self.rawObject.cs_setValue(newValue, forKVCKey: attribute) }
}
/**
Accesses or mutates the property value via its `NSAttributeDescription`, which can be accessed from the `enumerateAttributes(_:)` method.
*/
public subscript(attribute: NSAttributeDescription) -> Any? {
get { return self.rawObject.cs_accessValueForKVCKey(attribute.name) }
set { self.rawObject.cs_setValue(newValue, forKVCKey: attribute.name) }
}
/**
Enumerates the all `NSAttributeDescription`s. The `attribute` argument can be used as the subscript key to access and mutate the property. The `sourceAttribute` can be used to access properties from the source `UnsafeSourceObject`.
*/
public func enumerateAttributes(_ closure: (_ attribute: NSAttributeDescription, _ sourceAttribute: NSAttributeDescription?) -> Void) {
for case let attribute as NSAttributeDescription in self.rawObject.entity.properties {
func enumerate(_ entity: NSEntityDescription, _ closure: (_ attribute: NSAttributeDescription, _ sourceAttribute: NSAttributeDescription?) -> Void) {
closure(attribute, self.sourceAttributesByDestinationKey[attribute.name])
if let superEntity = entity.superentity {
enumerate(superEntity, closure)
}
for case let attribute as NSAttributeDescription in entity.properties {
closure(attribute, self.sourceAttributesByDestinationKey[attribute.name])
}
}
enumerate(self.rawObject.entity, closure)
}
// MARK: Internal
internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]) {
internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [KeyPathString: NSAttributeDescription]) {
self.rawObject = rawObject
self.sourceAttributesByDestinationKey = sourceAttributesByDestinationKey
}
// MARK: Private
// MARK: FilePrivate
private let rawObject: NSManagedObject
private let sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]
fileprivate let rawObject: NSManagedObject
fileprivate let sourceAttributesByDestinationKey: [KeyPathString: NSAttributeDescription]
}
@@ -253,7 +339,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
// MARK: SchemaMappingProvider
public func createMappingModel(from sourceSchema: DynamicSchema, to destinationSchema: DynamicSchema, storage: LocalStorage) throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
public func cs_createMappingModel(from sourceSchema: DynamicSchema, to destinationSchema: DynamicSchema, storage: LocalStorage) throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
let sourceModel = sourceSchema.rawModel()
let destinationModel = destinationSchema.rawModel()
@@ -266,7 +352,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
)
func expression(forSource sourceEntity: NSEntityDescription) -> NSExpression {
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), $\(NSMigrationManagerKey).\(#keyPath(NSMigrationManager.sourceContext)), \(false))")
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), FUNCTION($\(NSMigrationManagerKey), \"\(#selector(getter: NSMigrationManager.sourceContext))\"), \(false))")
}
let sourceEntitiesByName = sourceModel.entitiesByName
@@ -341,22 +427,25 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
let destinationAttribute = destination.attribute
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationAttribute.name
propertyMapping.valueExpression = NSExpression(format: "$\(NSMigrationSourceObjectKey).\(sourceAttribute.name)")
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceAttribute.name)\")")
attributeMappings.append(propertyMapping)
}
return attributeMappings
}
let entityMappingName = entityMapping.name!
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
let sourceRelationships = sourceEntity.cs_resolvedRelationshipRenamingIdentities()
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
var relationshipMappings: [NSPropertyMapping] = []
for (_, destination) in destinationRelationships {
for (renamingIdentifier, destination) in destinationRelationships {
let sourceRelationship = sourceRelationships[renamingIdentifier]!.relationship
let destinationRelationship = destination.relationship
let sourceRelationshipName = sourceRelationship.name
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationRelationship.name
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"destinationInstancesForSourceRelationshipNamed:sourceInstances:\", \"\(sourceRelationshipName)\", FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceRelationshipName)\"))")
relationshipMappings.append(propertyMapping)
}
return relationshipMappings
@@ -388,7 +477,7 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
let transformedRenamingIdentifiers = Set(destinationAttributes.keys)
.intersection(sourceAttributes.keys)
var sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription] = [:]
var sourceAttributesByDestinationKey: [KeyPathString: NSAttributeDescription] = [:]
for renamingIdentifier in transformedRenamingIdentifiers {
let sourceAttribute = sourceAttributes[renamingIdentifier]!.attribute
@@ -397,17 +486,24 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
}
userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] = sourceAttributesByDestinationKey
}
let entityMappingName = entityMapping.name!
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
let sourceRelationships = sourceEntity.cs_resolvedRelationshipRenamingIdentities()
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
let transformedRenamingIdentifiers = Set(destinationRelationships.keys)
.intersection(sourceRelationships.keys)
var relationshipMappings: [NSPropertyMapping] = []
for (_, destination) in destinationRelationships {
let destinationRelationship = destination.relationship
for renamingIdentifier in transformedRenamingIdentifiers {
let sourceRelationship = sourceRelationships[renamingIdentifier]!.relationship
let destinationRelationship = destinationRelationships[renamingIdentifier]!.relationship
let sourceRelationshipName = sourceRelationship.name
let destinationRelationshipName = destinationRelationship.name
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationRelationship.name
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
propertyMapping.name = destinationRelationshipName
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"destinationInstancesForSourceRelationshipNamed:sourceInstances:\", \"\(sourceRelationshipName)\", FUNCTION($\(NSMigrationSourceObjectKey), \"\(#selector(NSManagedObject.value(forKey:)))\", \"\(sourceRelationshipName)\"))")
relationshipMappings.append(propertyMapping)
}
return relationshipMappings
@@ -439,27 +535,27 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
let userInfo = mapping.userInfo!
let transformer = userInfo[CustomEntityMigrationPolicy.UserInfoKey.transformer]! as! CustomMapping.Transformer
let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [KeyPath: NSAttributeDescription]
let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [KeyPathString: NSAttributeDescription]
var dInstance: NSManagedObject?
var destinationObject: UnsafeDestinationObject?
try transformer(
UnsafeSourceObject(sInstance),
{
if let destinationObject = destinationObject {
return destinationObject
}
let rawObject = NSEntityDescription.insertNewObject(
forEntityName: mapping.destinationEntityName!,
into: manager.destinationContext
)
dInstance = rawObject
return UnsafeDestinationObject(rawObject, sourceAttributesByDestinationKey)
destinationObject = UnsafeDestinationObject(rawObject, sourceAttributesByDestinationKey)
return destinationObject!
}
)
if let dInstance = dInstance {
if let dInstance = destinationObject?.rawObject {
manager.associate(
sourceInstance: sInstance,
withDestinationInstance: dInstance,
for: mapping
)
manager.associate(sourceInstance: sInstance, withDestinationInstance: dInstance, for: mapping)
}
}
@@ -489,8 +585,8 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
var insertMappings: Set<CustomMapping> = []
var copyMappings: Set<CustomMapping> = []
var transformMappings: Set<CustomMapping> = []
var allMappedSourceKeys: [KeyPath: KeyPath] = [:]
var allMappedDestinationKeys: [KeyPath: KeyPath] = [:]
var allMappedSourceKeys: [KeyPathString: KeyPathString] = [:]
var allMappedDestinationKeys: [KeyPathString: KeyPathString] = [:]
let sourceRenamingIdentifiers = sourceModel.cs_resolvedRenamingIdentities()
let sourceEntityNames = sourceModel.entitiesByName
@@ -580,77 +676,76 @@ open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
allMappedSourceKeys[sourceEntity] = destinationEntity
allMappedDestinationKeys[destinationEntity] = sourceEntity
}
}
for renamingIdentifier in transformedRenamingIdentifiers {
for renamingIdentifier in transformedRenamingIdentifiers {
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
let sourceEntityName = sourceEntity.name!
let destinationEntityName = destinationEntity.name!
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
let sourceEntityName = sourceEntity.name!
let destinationEntityName = destinationEntity.name!
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
case (nil, nil):
if sourceEntity.versionHash == destinationEntity.versionHash {
case (nil, nil):
if sourceEntity.versionHash == destinationEntity.versionHash {
copyMappings.insert(
.copyEntity(
sourceEntity: sourceEntityName,
destinationEntity: destinationEntityName
)
copyMappings.insert(
.copyEntity(
sourceEntity: sourceEntityName,
destinationEntity: destinationEntityName
)
}
else {
transformMappings.insert(
.transformEntity(
sourceEntity: sourceEntityName,
destinationEntity: destinationEntityName,
transformer: CustomMapping.inferredTransformation
)
)
}
else {
transformMappings.insert(
.transformEntity(
sourceEntity: sourceEntityName,
destinationEntity: destinationEntityName,
transformer: CustomMapping.inferredTransformation
)
}
allMappedSourceKeys[sourceEntityName] = destinationEntityName
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
case (""?, nil):
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
allMappedDestinationKeys[destinationEntityName] = ""
case (nil, ""?):
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
allMappedSourceKeys[sourceEntityName] = ""
default:
continue
)
}
}
for renamingIdentifier in removedRenamingIdentifiers {
allMappedSourceKeys[sourceEntityName] = destinationEntityName
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
let sourceEntityName = sourceEntity.name!
switch allMappedSourceKeys[sourceEntityName] {
case nil:
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
allMappedSourceKeys[sourceEntityName] = ""
default:
continue
}
}
for renamingIdentifier in addedRenamingIdentifiers {
case (""?, nil):
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
allMappedDestinationKeys[destinationEntityName] = ""
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
let destinationEntityName = destinationEntity.name!
switch allMappedDestinationKeys[destinationEntityName] {
case nil:
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
allMappedDestinationKeys[destinationEntityName] = ""
default:
continue
}
case (nil, ""?):
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
allMappedSourceKeys[sourceEntityName] = ""
default:
continue
}
}
for renamingIdentifier in removedRenamingIdentifiers {
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
let sourceEntityName = sourceEntity.name!
switch allMappedSourceKeys[sourceEntityName] {
case nil:
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
allMappedSourceKeys[sourceEntityName] = ""
default:
continue
}
}
for renamingIdentifier in addedRenamingIdentifiers {
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
let destinationEntityName = destinationEntity.name!
switch allMappedDestinationKeys[destinationEntityName] {
case nil:
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
allMappedDestinationKeys[destinationEntityName] = ""
default:
continue
}
}
return (deleteMappings, insertMappings, copyMappings, transformMappings)

View File

@@ -47,7 +47,7 @@ public extension DataStack {
- parameter storage: the storage
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
*/
public func addStorage<T: StorageInterface>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
public func addStorage<T>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) {
self.coordinator.performAsynchronously {
@@ -173,7 +173,7 @@ public extension DataStack {
do {
try storage.eraseStorageAndWait(
try storage.cs_eraseStorageAndWait(
metadata: metadata,
soureModelHint: self.schemaHistory.schema(for: metadata)?.rawModel()
)
@@ -341,7 +341,7 @@ public extension DataStack {
)
_ = try self.schemaHistory
.schema(for: metadata)
.flatMap({ try storage.eraseStorageAndWait(soureModel: $0.rawModel()) })
.flatMap({ try storage.cs_eraseStorageAndWait(soureModel: $0.rawModel()) })
_ = try self.createPersistentStoreFromStorage(
storage,
finalURL: cacheFileURL,
@@ -575,6 +575,7 @@ public extension DataStack {
sourceModel: sourceModel,
destinationModel: destinationModel,
mappingModel: mappingModel,
migrationType: migrationType,
progress: childProgress
)
}
@@ -647,8 +648,9 @@ public extension DataStack {
let mappingProviders = storage.migrationMappingProviders
do {
try withExtendedLifetime((sourceSchema.rawModel(), destinationSchema.rawModel())) { (sourceModel, destinationModel) in
try withExtendedLifetime((sourceSchema.rawModel(), destinationSchema.rawModel())) {
let (sourceModel, destinationModel) = $0
let mapping = try mappingProviders.findMapping(
sourceSchema: sourceSchema,
destinationSchema: destinationSchema,
@@ -679,10 +681,74 @@ public extension DataStack {
return nil
}
private func startMigrationForStorage<T: LocalStorage>(_ storage: T, sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, progress: Progress) throws {
private func startMigrationForStorage<T: LocalStorage>(_ storage: T, sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType, progress: Progress) throws {
do {
try storage.cs_finalizeStorageAndWait(soureModelHint: sourceModel)
}
catch {
throw CoreStoreError(error)
}
let fileURL = storage.fileURL
if case .lightweight = migrationType {
do {
let timerQueue = DispatchQueue(
label: "DataStack.lightweightMigration.timerQueue",
qos: .utility,
attributes: []
)
let estimatedTime: TimeInterval = 60 * 3 // 3 mins
let interval: TimeInterval = 1
let fakeTotalUnitCount: Float = 0.9 * Float(progress.totalUnitCount)
var fakeProgress: Float = 0
var recursiveCheck: () -> Void = {}
recursiveCheck = {
guard fakeProgress < 1 else {
return
}
progress.completedUnitCount = Int64(fakeTotalUnitCount * fakeProgress)
fakeProgress += Float(interval / estimatedTime)
timerQueue.asyncAfter(
deadline: .now() + interval,
execute: recursiveCheck
)
}
timerQueue.async(execute: recursiveCheck)
_ = try withExtendedLifetime(NSPersistentStoreCoordinator(managedObjectModel: destinationModel)) { (coordinator: NSPersistentStoreCoordinator) in
try coordinator.addPersistentStoreSynchronously(
type(of: storage).storeType,
configuration: storage.configuration,
URL: fileURL,
options: storage.dictionary(
forOptions: storage.localStorageOptions.union(.allowSynchronousLightweightMigration)
)
)
}
timerQueue.sync {
fakeProgress = 1
}
try storage.cs_finalizeStorageAndWait(soureModelHint: destinationModel)
progress.completedUnitCount = progress.totalUnitCount
return
}
catch {
throw CoreStoreError(error)
}
}
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
.appendingPathComponent(Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack")
.appendingPathComponent(ProcessInfo().globallyUniqueString)
@@ -716,6 +782,13 @@ public extension DataStack {
destinationType: type(of: storage).storeType,
destinationOptions: nil
)
let temporaryStorage = SQLiteStore(
fileURL: temporaryFileURL,
configuration: storage.configuration,
migrationMappingProviders: storage.migrationMappingProviders,
localStorageOptions: storage.localStorageOptions
)
try temporaryStorage.cs_finalizeStorageAndWait(soureModelHint: destinationModel)
}
catch {
@@ -756,17 +829,17 @@ fileprivate extension Array where Element == SchemaMappingProvider {
case let element as CustomSchemaMappingProvider
where element.sourceVersion == sourceSchema.modelVersion && element.destinationVersion == destinationSchema.modelVersion:
return try element.createMappingModel(from: sourceSchema, to: destinationSchema, storage: storage)
return try element.cs_createMappingModel(from: sourceSchema, to: destinationSchema, storage: storage)
case let element as XcodeSchemaMappingProvider
where element.sourceVersion == sourceSchema.modelVersion && element.destinationVersion == destinationSchema.modelVersion:
return try element.createMappingModel(from: sourceSchema, to: destinationSchema, storage: storage)
return try element.cs_createMappingModel(from: sourceSchema, to: destinationSchema, storage: storage)
default:
continue
}
}
return try InferredSchemaMappingProvider()
.createMappingModel(from: sourceSchema, to: destinationSchema, storage: storage)
.cs_createMappingModel(from: sourceSchema, to: destinationSchema, storage: storage)
}
}

View File

@@ -33,12 +33,12 @@ import CoreData
public extension DataStack {
/**
Creates an `ObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`.
Creates an `ObjectMonitor` for the specified `DynamicObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `DynamicObject`.
- parameter object: the `NSManagedObject` to observe changes from
- parameter object: the `DynamicObject` to observe changes from
- returns: a `ObjectMonitor` that monitors changes to `object`
*/
public func monitorObject<T: DynamicObject>(_ object: T) -> ObjectMonitor<T> {
public func monitorObject<D>(_ object: D) -> ObjectMonitor<D> {
CoreStore.assert(
Thread.isMainThread,
@@ -48,25 +48,25 @@ public extension DataStack {
}
/**
Creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
public func monitorList<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.monitorList(from, fetchClauses)
}
/**
Creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public func monitorList<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
public func monitorList<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
CoreStore.assert(
Thread.isMainThread,
@@ -82,32 +82,49 @@ public extension DataStack {
CoreStore.assert(
fetchRequest.sortDescriptors?.isEmpty == false,
"An \(cs_typeName(ListMonitor<T>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
"An \(cs_typeName(ListMonitor<D>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy<D>.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
)
}
)
}
/**
Asynchronously creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let monitor = dataStack.monitorList(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
return self.monitorList(clauseChain.from, clauseChain.fetchClauses)
}
/**
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: FetchClause...) {
public func monitorList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ fetchClauses: FetchClause...) {
self.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
}
/**
Asynchronously creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public func monitorList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ fetchClauses: [FetchClause]) {
public func monitorList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ fetchClauses: [FetchClause]) {
CoreStore.assert(
Thread.isMainThread,
@@ -123,7 +140,7 @@ public extension DataStack {
CoreStore.assert(
fetchRequest.sortDescriptors?.isEmpty == false,
"An \(cs_typeName(ListMonitor<T>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
"An \(cs_typeName(ListMonitor<D>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy<D>.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
)
},
createAsynchronously: createAsynchronously
@@ -131,27 +148,53 @@ public extension DataStack {
}
/**
Creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
```
dataStack.monitorList(
{ (monitor) in
self.monitor = monitor
},
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
self.monitorList(
createAsynchronously: createAsynchronously,
clauseChain.from,
clauseChain.fetchClauses
)
}
/**
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.monitorSectionedList(from, sectionBy, fetchClauses)
}
/**
Creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
public func monitorSectionedList<T: DynamicObject>(_ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
CoreStore.assert(
Thread.isMainThread,
@@ -168,34 +211,56 @@ public extension DataStack {
CoreStore.assert(
fetchRequest.sortDescriptors?.isEmpty == false,
"An \(cs_typeName(ListMonitor<T>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
"An \(cs_typeName(ListMonitor<D>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy<D>.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
)
}
)
}
/**
Asynchronously creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
```
let monitor = dataStack.monitorSectionedList(
From<MyPersonEntity>()
.sectionBy(\.age, { "\($0!) years old" })
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
*/
public func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
return self.monitorSectionedList(
clauseChain.from,
clauseChain.sectionBy,
clauseChain.fetchClauses
)
}
/**
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
}
/**
Asynchronously creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
- parameter from: a `From` clause indicating the entity type
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/
public func monitorSectionedList<T: DynamicObject>(createAsynchronously: @escaping (ListMonitor<T>) -> Void, _ from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
CoreStore.assert(
Thread.isMainThread,
@@ -212,10 +277,36 @@ public extension DataStack {
CoreStore.assert(
fetchRequest.sortDescriptors?.isEmpty == false,
"An \(cs_typeName(ListMonitor<T>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
"An \(cs_typeName(ListMonitor<D>.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy<D>.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
)
},
createAsynchronously: createAsynchronously
)
}
/**
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
```
dataStack.monitorSectionedList(
{ (monitor) in
self.monitor = monitor
},
From<MyPersonEntity>()
.sectionBy(\.age, { "\($0!) years old" })
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
*/
public func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
self.monitorSectionedList(
createAsynchronously: createAsynchronously,
clauseChain.from,
clauseChain.sectionBy,
clauseChain.fetchClauses
)
}
}

View File

@@ -34,57 +34,57 @@ extension DataStack: FetchableSource, QueryableSource {
// MARK: FetchableSource
/**
Fetches the `NSManagedObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
Fetches the `DynamicObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
- parameter object: a reference to the object created/fetched outside the `DataStack`
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
public func fetchExisting<T: DynamicObject>(_ object: T) -> T? {
public func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
return self.mainContext.fetchExisting(object)
}
/**
Fetches the `NSManagedObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
Fetches the `DynamicObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
- returns: the `DynamicObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
public func fetchExisting<T: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
public func fetchExisting<D: DynamicObject>(_ objectID: NSManagedObjectID) -> D? {
return self.mainContext.fetchExisting(objectID)
}
/**
Fetches the `NSManagedObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
Fetches the `DynamicObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
- parameter objects: an array of `DynamicObject`s created/fetched outside the `DataStack`
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
*/
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objects: S) -> [D] where S.Iterator.Element == D {
return self.mainContext.fetchExisting(objects)
}
/**
Fetches the `NSManagedObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
Fetches the `DynamicObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
- returns: the `DynamicObject` array for objects that exists in the `DataStack`
*/
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
public func fetchExisting<D: DynamicObject, S: Sequence>(_ objectIDs: S) -> [D] where S.Iterator.Element == NSManagedObjectID {
return self.mainContext.fetchExisting(objectIDs)
}
/**
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
public func fetchOne<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> D? {
CoreStore.assert(
Thread.isMainThread,
@@ -94,13 +94,13 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
- returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
public func fetchOne<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> D? {
CoreStore.assert(
Thread.isMainThread,
@@ -110,13 +110,34 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeen = dataStack.fetchOne(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType`
*/
public func fetchOne<B: FetchChainableBuilderType>(_ clauseChain: B) -> B.ObjectType? {
CoreStore.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.fetchOne(clauseChain)
}
/**
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
public func fetchAll<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [D]? {
CoreStore.assert(
Thread.isMainThread,
@@ -126,13 +147,13 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
- returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
public func fetchAll<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [D]? {
CoreStore.assert(
Thread.isMainThread,
@@ -142,13 +163,34 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let people = dataStack.fetchAll(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType`
*/
public func fetchAll<B: FetchChainableBuilderType>(_ clauseChain: B) -> [B.ObjectType]? {
CoreStore.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.fetchAll(clauseChain)
}
/**
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
public func fetchCount<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> Int? {
CoreStore.assert(
Thread.isMainThread,
@@ -158,13 +200,13 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
public func fetchCount<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> Int? {
CoreStore.assert(
Thread.isMainThread,
@@ -174,13 +216,34 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let numberOfAdults = dataStack.fetchCount(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public func fetchCount<B: FetchChainableBuilderType>(_ clauseChain: B) -> Int? {
CoreStore.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.fetchCount(clauseChain)
}
/**
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
public func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
CoreStore.assert(
Thread.isMainThread,
@@ -190,13 +253,13 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
public func fetchObjectID<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
Thread.isMainThread,
@@ -206,13 +269,34 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let youngestTeenID = dataStack.fetchObjectID(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType`
*/
public func fetchObjectID<B: FetchChainableBuilderType>(_ clauseChain: B) -> NSManagedObjectID? {
CoreStore.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.fetchObjectID(clauseChain)
}
/**
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
public func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
CoreStore.assert(
Thread.isMainThread,
@@ -222,13 +306,13 @@ extension DataStack: FetchableSource, QueryableSource {
}
/**
Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
public func fetchObjectIDs<D>(_ from: From<D>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
Thread.isMainThread,
@@ -237,6 +321,27 @@ extension DataStack: FetchableSource, QueryableSource {
return self.mainContext.fetchObjectIDs(from, fetchClauses)
}
/**
Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
```
let idsOfAdults = dataStack.fetchObjectIDs(
From<MyPersonEntity>()
.where(\.age > 18)
.orderBy(.ascending(\.age))
)
```
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
*/
public func fetchObjectIDs<B: FetchChainableBuilderType>(_ clauseChain: B) -> [NSManagedObjectID]? {
CoreStore.assert(
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.fetchObjectIDs(clauseChain)
}
// MARK: QueryableSource
@@ -250,7 +355,7 @@ extension DataStack: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
public func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: QueryClause...) -> U? {
CoreStore.assert(
Thread.isMainThread,
@@ -269,7 +374,7 @@ extension DataStack: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
public func queryValue<D, U: QueryableAttributeType>(_ from: From<D>, _ selectClause: Select<D, U>, _ queryClauses: [QueryClause]) -> U? {
CoreStore.assert(
Thread.isMainThread,
@@ -278,6 +383,29 @@ extension DataStack: FetchableSource, QueryableSource {
return self.mainContext.queryValue(from, selectClause, queryClauses)
}
/**
Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
```
let averageAdultAge = dataStack.queryValue(
From<MyPersonEntity>()
.select(Int.self, .average(\.age))
.where(\.age > 18)
)
```
- parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request.
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
*/
public func queryValue<B: QueryChainableBuilderType>(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType {
CoreStore.assert(
Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
}
/**
Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
@@ -288,7 +416,7 @@ extension DataStack: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
public func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
CoreStore.assert(
Thread.isMainThread,
@@ -307,7 +435,7 @@ extension DataStack: FetchableSource, QueryableSource {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
public func queryAttributes<D>(_ from: From<D>, _ selectClause: Select<D, NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
CoreStore.assert(
Thread.isMainThread,
@@ -316,6 +444,38 @@ extension DataStack: FetchableSource, QueryableSource {
return self.mainContext.queryAttributes(from, selectClause, queryClauses)
}
/**
Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses.
A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
```
let results = dataStack.queryAttributes(
From<MyPersonEntity>()
.select(
NSDictionary.self,
.attribute(\.age, as: "age"),
.count(\.age, as: "numberOfPeople")
)
.groupBy(\.age)
)
for dictionary in results! {
let age = dictionary["age"] as! Int
let count = dictionary["numberOfPeople"] as! Int
print("There are \(count) people who are \(age) years old."
}
```
- parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request.
- returns: the result of the the query as specified by the `QueryChainableBuilderType`
*/
public func queryAttributes<B: QueryChainableBuilderType>(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary {
CoreStore.assert(
Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread."
)
return self.mainContext.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses)
}
// MARK: FetchableSource, QueryableSource
@@ -328,11 +488,11 @@ extension DataStack: FetchableSource, QueryableSource {
}
// MARK: Deprecated
// MARK: Obsoleted
@available(*, deprecated, renamed: "unsafeContext()")
@available(*, obsoleted: 3.1, renamed: "unsafeContext()")
public func internalContext() -> NSManagedObjectContext {
return self.unsafeContext()
fatalError()
}
}

View File

@@ -32,10 +32,10 @@ import CoreData
public extension DataStack {
/**
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`.
Performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(userInfo: T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(error: CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter completion: the closure executed after the save completes. The `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)`.
- parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
*/
public func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, completion: @escaping (AsynchronousDataTransaction.Result<T>) -> Void) {
@@ -47,11 +47,11 @@ public extension DataStack {
}
/**
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`.
Performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the argument of the `success` closure. Any errors thrown from inside the `task` will be wrapped in a `CoreStoreError` and reported in the `failure` closure. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter success: the closure executed after the save succeeds. The `T` argument of the closure will be the value returned from `task`.
- 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)`.
- parameter failure: the closure executed if the save fails or if any errors are thrown within `task`. Cancelled `task`s will be indicated by `CoreStoreError.userCancelled`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
*/
public func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, success: @escaping (T) -> Void, failure: @escaping (CoreStoreError) -> Void) {
@@ -78,6 +78,10 @@ public extension DataStack {
}
transaction.autoCommit { (_, error) in
defer {
withExtendedLifetime((self, transaction), {})
}
if let error = error {
failure(error)
@@ -91,7 +95,7 @@ public extension DataStack {
}
/**
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`.
Performs a transaction synchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the return value of `perform(synchronous:)`. Any errors thrown from inside the `task` will be thrown from `perform(synchronous:)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the synchronous non-escaping closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter waitForAllObservers: When `true`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks. When `false`, this method does not wait for observers to be notified of the changes before returning. This results in lower risk for deadlocks, but the updated data may not have been propagated to the `DataStack` after returning. Defaults to `true`.
@@ -106,6 +110,10 @@ public extension DataStack {
)
return try transaction.transactionQueue.cs_sync {
defer {
withExtendedLifetime((self, transaction), {})
}
let userInfo: T
do {
@@ -131,7 +139,7 @@ public extension DataStack {
}
/**
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.
Begins a non-contiguous transaction where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
- prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
@@ -146,7 +154,7 @@ public extension DataStack {
}
/**
Refreshes all registered objects `NSManagedObject`s in the `DataStack`.
Refreshes all registered objects `NSManagedObject`s or `CoreStoreObject`s in the `DataStack`.
*/
public func refreshAndMergeAllObjects() {
@@ -160,11 +168,6 @@ public extension DataStack {
// MARK: Deprecated
/**
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 func beginAsynchronous(_ closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
@@ -186,12 +189,6 @@ public extension DataStack {
}
}
/**
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 `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 func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
@@ -214,9 +211,9 @@ public extension DataStack {
}
switch transaction.result {
case nil: return nil
case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges)
case (_, let error?)?: return SaveResult(error)
case .none: return nil
case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges)
case .some(_, let error?): return SaveResult(error)
}
}
}

View File

@@ -34,19 +34,27 @@ import CoreData
*/
public final class DataStack: Equatable {
/**
The resolved application name, used by the `DataStack` as the default Xcode model name (.xcdatamodel filename) if not explicitly provided.
*/
public static let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData"
/**
Convenience initializer for `DataStack` that creates a `SchemaHistory` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set (e.g. in Unit Tests).
- parameter xcodeModelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set (e.g. in Unit Tests).
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
public convenience init(modelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
public convenience init(xcodeModelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
self.init(
schemaHistory: SchemaHistory(
modelName: modelName,
bundle: bundle,
XcodeDataModelSchema.from(
modelName: xcodeModelName,
bundle: bundle,
migrationChain: migrationChain
),
migrationChain: migrationChain
)
)
@@ -102,9 +110,6 @@ public final class DataStack: Equatable {
*/
public required init(schemaHistory: SchemaHistory) {
// TODO: test before release (rolled back)
// _ = DataStack.isGloballyInitialized
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
@@ -328,7 +333,7 @@ public final class DataStack: Equatable {
at: fileURL,
options: storeOptions
)
try storage.eraseStorageAndWait(
try storage.cs_eraseStorageAndWait(
metadata: metadata,
soureModelHint: self.schemaHistory.schema(for: metadata)?.rawModel()
)
@@ -425,7 +430,7 @@ public final class DataStack: Equatable {
)
_ = try self.schemaHistory
.schema(for: metadata)
.flatMap({ try storage.eraseStorageAndWait(soureModel: $0.rawModel()) })
.flatMap({ try storage.cs_eraseStorageAndWait(soureModel: $0.rawModel()) })
_ = try self.createPersistentStoreFromStorage(
storage,
finalURL: cacheFileURL,
@@ -459,7 +464,7 @@ public final class DataStack: Equatable {
```
- Important: Do not use this method to store thread-sensitive data.
*/
private let userInfo = UserInfo()
public let userInfo = UserInfo()
// MARK: Equatable
@@ -474,8 +479,6 @@ public final class DataStack: Equatable {
internal static var defaultConfigurationName = "PF_DEFAULT_CONFIGURATION_NAME"
internal static let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData"
internal let coordinator: NSPersistentStoreCoordinator
internal let rootSavingContext: NSManagedObjectContext
internal let mainContext: NSManagedObjectContext
@@ -570,7 +573,7 @@ public final class DataStack: Equatable {
self.finalConfigurationsByEntityIdentifier[entityIdentifier]?.insert(configurationName)
}
}
storage.didAddToDataStack(self)
storage.cs_didAddToDataStack(self)
return persistentStore
}
@@ -582,13 +585,6 @@ public final class DataStack: Equatable {
// MARK: Private
// TODO: test before release (rolled back)
// private static let isGloballyInitialized: Bool = {
//
// NSManagedObject.cs_swizzleMethodsForLogging()
// return true
// }()
private var persistentStoresByFinalConfiguration = [String: NSPersistentStore]()
private var finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set<String>]()
@@ -610,20 +606,25 @@ public final class DataStack: Equatable {
// MARK: Deprecated
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@available(*, deprecated: 3.1, message: "Use the new DataStack.init(schemaHistory:) initializer passing a LegacyXcodeDataModelSchema instance as argument")
@available(*, deprecated, renamed: "init(xcodeModelName:bundle:migrationChain:)")
public convenience init(modelName: XcodeDataModelFileName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
self.init(
xcodeModelName: modelName,
bundle: bundle,
migrationChain: migrationChain
)
}
@available(*, deprecated, message: "Use the new DataStack.init(schemaHistory:) initializer passing an UnsafeDataModelSchema instance as argument")
public convenience init(model: NSManagedObjectModel, migrationChain: MigrationChain = nil) {
let modelVersion = migrationChain.leafVersions.first!
self.init(
schemaHistory: SchemaHistory(
allSchema: [
LegacyXcodeDataModelSchema(
UnsafeDataModelSchema(
modelName: modelVersion,
model: model
)
@@ -634,10 +635,7 @@ public final class DataStack: Equatable {
)
}
/**
Returns the entity name-to-class type mapping from the `DataStack`'s model.
*/
@available(*, deprecated: 3.1, message: "Use the new DataStack.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
@available(*, deprecated, message: "Use the new DataStack.entityTypesByName(for:) method passing `NSManagedObject.self` as argument.")
public var entityTypesByName: [EntityName: NSManagedObject.Type] {
return self.entityTypesByName(for: NSManagedObject.self)

View File

@@ -33,12 +33,6 @@ import Foundation
*/
public final class DefaultLogger: CoreStoreLogger {
/**
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false`.
*/
// TODO: test before release (rolled back)
// public var enableObjectConcurrencyDebugging: Bool = false
/**
Creates a `DefaultLogger`.
*/

View File

@@ -0,0 +1,193 @@
//
// DynamicKeyPath.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
// MARK: - DynamicKeyPath
/**
Used only for utility methods.
*/
public protocol DynamicKeyPath {
/**
The DynamicObject type
*/
associatedtype ObjectType
/**
The Value type
*/
associatedtype ValueType
/**
The keyPath string
*/
var cs_keyPathString: String { get }
}
// MARK: - KeyPathString
public extension KeyPathString {
/**
Extracts the keyPath string from the property.
```
let keyPath = String(keyPath: \Person.nickname)
```
*/
public init<O: NSManagedObject, V>(keyPath: KeyPath<O, V>) {
self = keyPath.cs_keyPathString
}
/**
Extracts the keyPath string from the property.
```
let keyPath = String(keyPath: \Person.nickname)
```
*/
public init<O: CoreStoreObject, K: DynamicKeyPath>(keyPath: KeyPath<O, K>) {
self = O.meta[keyPath: keyPath].cs_keyPathString
}
}
// MARK: - KeyPath: DynamicKeyPath
// TODO: SE-0143 is not implemented: https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
//extension KeyPath: DynamicKeyPath where Root: NSManagedObject, Value: ImportableAttributeType {
extension KeyPath: DynamicKeyPath {
public typealias ObjectType = Root
public typealias ValueType = Value
public var cs_keyPathString: String {
return self._kvcKeyPathString!
}
}
// MARK: - ValueContainer.Required: DynamicKeyPath
extension ValueContainer.Required: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = V
public var cs_keyPathString: String {
return self.keyPath
}
}
// MARK: - ValueContainer.Optional: DynamicKeyPath
extension ValueContainer.Optional: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = V
public var cs_keyPathString: String {
return self.keyPath
}
}
// MARK: - TransformableContainer.Required: DynamicKeyPath
extension TransformableContainer.Required: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = V
public var cs_keyPathString: String {
return self.keyPath
}
}
// MARK: - TransformableContainer.Optional: DynamicKeyPath
extension TransformableContainer.Optional: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = V
public var cs_keyPathString: String {
return self.keyPath
}
}
// MARK: - RelationshipContainer.ToOne: DynamicKeyPath
extension RelationshipContainer.ToOne: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = D
public var cs_keyPathString: String {
return self.keyPath
}
}
// MARK: - RelationshipContainer.ToManyOrdered: DynamicKeyPath
extension RelationshipContainer.ToManyOrdered: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = D
public var cs_keyPathString: String {
return self.keyPath
}
}
// MARK: - RelationshipContainer.ToManyUnordered: DynamicKeyPath
extension RelationshipContainer.ToManyUnordered: DynamicKeyPath {
public typealias ObjectType = O
public typealias ValueType = D
public var cs_keyPathString: String {
return self.keyPath
}
}

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