Compare commits

...

223 Commits
2.0.0 ... 4.0.5

Author SHA1 Message Date
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
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 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
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
John Estropia
feb0e30735 tag as beta 2017-05-12 14:46:28 +09:00
John Rommel Estropia
9c25336ff6 WIP: documentation 2017-05-12 01:42:19 +09:00
John Estropia
66bef87422 WIP: documentation 2017-05-11 20:55:31 +09:00
John Rommel Estropia
dd2949ee18 WIP: documentation 2017-05-11 00:03:13 +09:00
John Estropia
e0abb9b0af Merge branch 'develop' into corestore4_develop
# Conflicts:
#	CoreStore.podspec
#	Sources/CoreStoreImportableAttributeType.swift
#	Sources/CoreStoreQueryableAttributeType.swift
#	Sources/Info.plist
#	Sources/NSManagedObjectModel+Setup.swift
2017-05-10 19:11:01 +09:00
John Estropia
42c28b064a remove unneeded swift flags 2017-05-10 12:47:40 +09:00
John Estropia
0b097b8c85 version bump 2017-05-10 12:43:18 +09:00
John Estropia
fce5d2f301 Flatten file directories (fixes #159) 2017-05-10 12:42:20 +09:00
John Rommel Estropia
8ff163af30 WIP: documentation 2017-05-10 02:00:47 +09:00
John Estropia
19abedfa9f WIP: documentation 2017-05-09 21:16:03 +09:00
John Estropia
48828fdca3 Custom migrations! 2017-05-09 17:58:41 +09:00
John Rommel Estropia
9d65a27557 WIP: custom migration 2017-05-09 03:10:35 +09:00
John Rommel Estropia
6d04806608 WIP 2017-04-26 08:31:37 +09:00
John Rommel Estropia
54129f7362 Merge branch 'corestore4_develop' of github.com:JohnEstropia/CoreStore into corestore4_develop 2017-04-25 22:08:58 +09:00
John Estropia
54c81d23f5 WIP: dynamic migrations 2017-04-25 18:08:43 +09:00
John Estropia
53ab140341 Improve refetch method (may fix #118) 2017-04-24 11:57:47 +09:00
John Estropia
9dc4331b26 oops 2017-04-21 21:21:47 +09:00
John Estropia
e6aa72fb5f support transformable values 2017-04-21 19:35:29 +09:00
John Estropia
274a54451a fix compiler errors 2017-04-21 15:07:26 +09:00
John Estropia
fe70b7a27d added tool to convert existing NSManagedObjectModels to the new CoreStoreSchema 2017-04-21 14:54:57 +09:00
John Estropia
02a660e4a6 WIP: Migrations 2017-04-20 20:26:11 +09:00
John Estropia
a543a4c94a Added a "userInfo" property to relevant types to allow external code to store custom data 2017-04-20 16:40:27 +09:00
John Estropia
fd14a18248 Unify generics usage in ListMonitor and ObjectMonitor 2017-04-20 10:42:47 +09:00
John Estropia
b0e2655bdf added a typealias for the object type contained in ListMonitor and ObjectMonitor 2017-04-19 17:04:34 +09:00
John Estropia
b6bc7c2edf allow edit() calls to any DynamicObject 2017-04-18 18:14:16 +09:00
John Estropia
1938f0d9de no need to be optional 2017-04-18 12:09:37 +09:00
John Estropia
94e6db669f added a way to lazily-initialize user info data 2017-04-18 12:02:39 +09:00
John Estropia
b1972b82f1 added way to store userInfo in DataStack and in transactions 2017-04-18 11:29:16 +09:00
John Rommel Estropia
5ffaca1375 WIP: docs 2017-04-18 08:02:07 +09:00
John Estropia
a73306fecb check correct queue for managed object value access 2017-04-12 19:22:18 +09:00
John Estropia
9f3db61ff7 WIP: allow migrations for CoreStoreObjects 2017-04-11 19:13:35 +09:00
John Estropia
e5ef4992d3 WIP: migrations for CoreStoreObjects 2017-04-07 21:57:45 +09:00
John Estropia
c0ae129b22 NSManagedObject features are now fully supported for CoreStoreObject types. MacOSX 10.12 onwards now support ListMonitors and ObjectMonitors 2017-04-07 20:14:13 +09:00
John Estropia
4aa1a63f9a updated unit tests with easier to understand examples 2017-04-06 20:45:54 +09:00
John Estropia
4fc10afe1e relationships done! 2017-04-06 20:28:17 +09:00
John Estropia
8b77e4e5a0 WIP: prototype for ManagedObjectProtocol 2017-04-05 21:56:19 +09:00
John Estropia
258c237100 It works! (WIP!) 2017-04-04 20:25:40 +09:00
John Estropia
6948db516d WIP: typesafe queries 2017-04-03 22:02:24 +09:00
John Estropia
b5d80fd272 WIP: Dynamic models (Goodbye xcdatamodel files!) 2017-04-03 21:41:25 +09:00
John Rommel Estropia
cdcd7d0416 removed deprecated functions in unit tests and demo app 2017-04-01 23:08:36 +09:00
John Rommel Estropia
a5162239d5 kick-off deprecations with 4.0 version bump 2017-04-01 21:23:50 +09:00
John Rommel Estropia
1ad6ac5769 accept NSManagedObject as Where predicate argument 2017-04-01 17:15:24 +09:00
John Rommel Estropia
ecb3d0cfa0 revert prototyped stack setup 2017-04-01 01:31:40 +09:00
John Estropia
81355fd9c5 update travis file for Xcode 8.3 2017-03-31 19:56:19 +09:00
John Estropia
97d7a276fe new auto-commit transaction methods 2017-03-31 19:44:18 +09:00
John Estropia
d72d1afe8b Merge branch 'develop' into corestore4_develop
# Conflicts:
#	CoreStore.xcodeproj/project.pbxproj
2017-03-28 11:38:02 +09:00
John Estropia
716e069984 version bump 2017-03-28 11:25:24 +09:00
John Estropia
881ee4af0a remove warnings when calling unsafeBitCast() 2017-03-28 10:54:08 +09:00
John Estropia
acc0ce1c32 Merge pull request #157 from ruslanskorb/fetched-objects-dynamicCast
Use `dynamicCast()` to cast `fetchedObjects` to `[T]?` without checking the type.
2017-03-28 10:10:23 +09:00
John Estropia
b97f6d6a0a Merge branch 'prototype/mainContextToPSC' into corestore4_develop 2017-03-27 14:08:07 +09:00
John Rommel Estropia
818abfc1a1 WIP 2017-03-27 01:48:51 +09:00
Ruslan Skorb
f055c54a66 [ListMonitor] Use dynamicCast() to cast fetchedObjects to [T]? without checking the type.
Type checking takes a time. So there is a performance problem when casting a large number of fetched objects to an array of a certain type using the operator `as?`.
2017-03-24 21:30:46 +02:00
John Estropia
cb6d5b015b WIP: prototyping new transaction structure 2017-03-24 21:15:51 +09:00
John Rommel Estropia
494965de23 changed protocol naming 2017-03-10 08:30:12 +09:00
John Estropia
fe25a9aa36 remove warnings when calling unsafeBitCast() 2017-03-09 18:59:37 +09:00
John Estropia
f21e4e12e0 Merge branch 'develop' into corestore4_develop 2017-03-09 18:08:35 +09:00
John Estropia
92890d1e1d Merge pull request #154 from ruslanskorb/remove-duplicate-code
[FetchedResultsControllerDelegate] Remove duplicate code.
2017-03-07 12:58:18 +09:00
Ruslan Skorb
0c483e0e19 [FetchedResultsControllerDelegate] Remove duplicate code. 2017-03-05 12:20:12 +02:00
John Rommel Estropia
6055685c00 WIP: compilable again now 2017-03-02 22:26:45 +09:00
John Rommel Estropia
ee71442b08 Merge branch 'develop' into corestore4_develop 2017-03-02 21:07:30 +09:00
John Estropia
341ec5e771 reverted unsafeDowncast usage to unsafeBitCast (It worked differently) 2017-03-01 19:56:13 +09:00
John Estropia
8569c3c524 WIP: rehaul of type-safe fetching and querying 2017-03-01 19:34:07 +09:00
John Estropia
3224fcf71d move type safety goodness 2017-02-21 19:17:06 +09:00
John Rommel Estropia
9ff1c9d545 declare operators as static functions 2017-02-19 20:05:23 +09:00
John Rommel Estropia
c40d17a6ad Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2017-02-19 09:56:40 +09:00
John Estropia
9d5e04854a extra extra type safety for attributes (fetching and importing) 2017-02-17 14:13:16 +09:00
John Estropia
d2fd03c1f0 Where clauses are now more strict with the argument types 2017-02-17 10:47:38 +09:00
John Rommel Estropia
7baaee493d unit test for scalar IDs for ImportableUniqueObject 2017-02-13 22:17:03 +09:00
John Estropia
03973790a8 revert recent swizzling update. sorry about that 2017-02-10 20:33:07 +09:00
John Estropia
7ee027f44d Test mainContext fetching directly from PSC. Needs benchmarking esp. with merging 2017-02-09 10:49:50 +09:00
John Estropia
19fea6953a Merge branch 'master' into develop 2017-02-08 13:13:27 +09:00
John Estropia
9f11b1005d added .swift-version file 2017-02-08 13:08:44 +09:00
John Estropia
698326f89a version bump 2017-02-07 18:21:54 +09:00
John Estropia
bdf6308d8f swift 3.1 support 2017-02-07 18:17:40 +09:00
John Estropia
69d96c53d6 WIP: object concurrency debugging utilities 2017-02-02 19:53:47 +09:00
John Estropia
7b961fa249 Display list of model files in bundle when requested modelname is not found 2017-02-01 19:03:59 +09:00
John Estropia
73450d0b29 WIP: minor conveniences to the ImportableUniqueObject protocol 2017-01-20 21:51:00 +09:00
John Estropia
6d83564a1a Swift 3 master candidate 2017-01-06 16:50:38 +09:00
John Estropia
c0d72799b4 Merge branch 'swift3_develop' into develop
# Conflicts:
#	.travis.yml
#	CoreStore.podspec
#	CoreStore.xcodeproj/project.pbxproj
#	Sources/Info.plist
2017-01-06 16:03:28 +09:00
John Estropia
06a1919e91 minor fixes 2017-01-06 15:56:47 +09:00
John Rommel Estropia
16def2d84b disable tests on iOS 8.2 and 8.1 (keeps failing due to xcode bug) 2016-12-31 13:14:50 +08:00
John Rommel Estropia
e9a2c58f32 travis bug 2016-12-31 11:26:35 +08:00
John Rommel Estropia
1a3e0dd4c6 CoreStore 3 master candidate 2016-12-31 11:03:03 +08:00
John Rommel Estropia
518bb134f9 merge fix 2016-12-26 14:55:06 +08:00
John Estropia
4d7feca848 Merge pull request #139 from deanWombourne/swift3_develop
Add an override to cs_typeName which deals with String explicitly.
2016-12-26 14:53:51 +08:00
John Rommel Estropia
64a80bf401 Swift 3.0.1 support 2016-12-26 14:51:36 +08:00
John Rommel Estropia
4d63fc744a Add String overload for cs_typeName (fixes #138) 2016-12-26 14:51:23 +08:00
Sam Dean
9480e372f1 Add an override to cs_typeName which deals with String explicitly. 2016-12-23 11:06:09 +00:00
John Rommel Estropia
23df460c35 require transaction logs path from icloud stores 2016-12-10 18:39:53 +09:00
John Rommel Estropia
1c233b7302 don't access iCloud's ubiquitous cache file 2016-12-10 09:43:45 +09:00
John Estropia
f42288802c Merge branch 'swift3_develop' of github.com:JohnEstropia/CoreStore into swift3_develop
# Conflicts:
#	Sources/Convenience/NSManagedObject+Convenience.swift
2016-12-08 19:00:38 +09:00
John Estropia
a27556f294 minor Swift 3 cleanup 2016-12-08 18:59:41 +09:00
John Rommel Estropia
e330291e1b support generics for KVC accessors 2016-12-03 10:13:50 +09:00
John Rommel Estropia
4a282150f0 utilities for safer KVO access in objects 2016-12-03 09:59:17 +09:00
John Rommel Estropia
5d2956d674 Make RecreateStoreOnModelMismatch flag work again (fixes #126) 2016-11-26 16:19:12 +09:00
John Estropia
92756fec42 always dispatch completion right after adding a store to the coordinator (allow stores to fully complete their run loop) 2016-11-17 16:27:28 +09:00
John Estropia
2b37daefe0 minor documentation updates 2016-11-17 14:31:06 +09:00
John Estropia
5724d4599e Merge pull request #122 from ruslanskorb/rename-error-type-to-error
`ErrorType` has been renamed to `Error` in Swift 3.
2016-11-17 13:34:03 +09:00
Ruslan Skorb
4a882e6108 ErrorType has been renamed to Error in Swift 3. 2016-11-15 19:16:18 +02:00
John Estropia
b230ed6400 FetchableSource and QueryableSource protocols 2016-11-15 18:00:39 +09:00
John Estropia
33a5c123aa resurrect utilities for creating NSFetchedResultsController (fixes #119) 2016-11-11 17:32:13 +09:00
John Estropia
73637321ce xcode 8.1 (swift 3.0.1) update 2016-11-11 14:03:37 +09:00
John Estropia
088f1717f9 Merge pull request #115 from deville/import-unique-objects-order
Import unique objects in the same order as the array of import sources (with fix for potential duplicates)
2016-11-11 11:46:27 +09:00
John Estropia
cff2bb1740 version bump 2016-10-27 19:16:17 +09:00
John Estropia
d902d62172 Turn off whole-module-optimization to prevent Swift compiler bugs (#113) 2016-10-27 18:41:27 +09:00
John Estropia
b955495012 Turn off whole-module-optimization to prevent Swift compiler bugs (#113) 2016-10-27 18:30:35 +09:00
Andrii Chernenko
d2e78a70e1 add test for the order of unique object import 2016-10-23 16:22:26 +02:00
Andrii Chernenko
970957cbc2 Merge branch 'duplicate-import-fix' into import-unique-objects-order 2016-10-23 14:52:34 +02:00
John Rommel Estropia
2f9e5db89f Added comment (fixes #106) 2016-10-16 14:40:25 +09:00
John Estropia
1789eb7daf Merge pull request #112 from JohnEstropia/revert-109-import-unique-objects-order
Revert "Import unique objects in the same order as the array of import sources"
2016-10-14 17:46:27 +09:00
John Estropia
3999654ee7 Revert "Import unique objects in the same order as the array of import sources" 2016-10-14 17:45:31 +09:00
Andrii Chernenko
4c3bec287c fix duplication when using importUniqueObjects with non-unique import sources 2016-10-12 02:01:23 +02:00
John Estropia
2a2d9b3483 Merge pull request #109 from deville/import-unique-objects-order
Import unique objects in the same order as the array of import sources
2016-10-10 20:29:59 +09:00
Andrii Chernenko
32a388e0ca import unique objects in the same order as the array of import sources 2016-10-08 23:14:22 +02:00
John Rommel Estropia
1a6fbad3d4 force dynamic dispatch on generic types 2016-10-09 00:52:18 +09:00
John Estropia
ac55f20f5f Merge pull request #108 from deville/type-method-dispatch-fix
Fix type method dispatch when importing objects
2016-10-08 10:43:21 +09:00
Andrii Chernenko
910b5039fd fix type method dispatch when importing objects 2016-10-07 15:26:45 +02:00
John Estropia
ffea06ee7e try again 2016-09-30 19:16:14 +09:00
John Estropia
a92d6cac02 try again 2016-09-30 19:08:17 +09:00
John Estropia
de5d660257 try again 2016-09-30 17:53:15 +09:00
John Estropia
55b2e6eecd try again 2016-09-30 17:36:48 +09:00
John Estropia
b64c776335 try again 2016-09-30 17:28:02 +09:00
John Estropia
432af667e8 try again 2016-09-30 17:08:04 +09:00
John Estropia
cf60a4bc2e updated travis.yml 2016-09-30 17:00:11 +09:00
John Estropia
c620859899 run demo project on CI 2016-09-30 13:58:11 +09:00
John Estropia
65ac069a0b skip observer testing on macOS 2016-09-30 13:32:31 +09:00
John Estropia
862ef27374 version bump, cleanup, unit test 2016-09-30 13:28:19 +09:00
John Estropia
243b6a76d5 Merge pull request #104 from colinmorelli/feature/sync-transaction-async-merge
Fixes #98 (deadlock when merge happens while main queue is querying)
2016-09-30 12:38:28 +09:00
Colin Morelli
8be20370d5 Fixes #98 (deadlock when merge happens while main queue is querying) 2016-09-29 14:47:51 -04:00
John Estropia
a9c0feae46 NSFetchRequest.affectedStores bug workaround 2016-09-27 19:02:24 +09:00
John Estropia
2e44f86eb6 Merge branch 'develop' into swift3_develop
# Conflicts:
#	Cartfile
#	Carthage/Checkouts/GCDKit
#	CoreStore.podspec
#	CoreStore.xcodeproj/project.pbxproj
#	CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj
#	CoreStoreTests/BaseTests/BaseTestCase.swift
#	CoreStoreTests/FromTests.swift
#	CoreStoreTests/GroupByTests.swift
#	CoreStoreTests/OrderByTests.swift
#	CoreStoreTests/StorageInterfaceTests.swift
#	CoreStoreTests/TweakTests.swift
#	CoreStoreTests/WhereTests.swift
#	README.md
#	Sources/Internal/CoreStoreFetchRequest.swift
#	Sources/Internal/NSManagedObjectContext+Querying.swift
#	Sources/Internal/NSManagedObjectModel+Setup.swift
#	Sources/Migrating/DataStack+Migration.swift
#	Sources/ObjectiveC/CSSQliteStore.swift
#	Sources/ObjectiveC/CSStorageInterface.swift
#	Sources/ObjectiveC/CoreStoreBridge.swift
#	Sources/Observing/ListMonitor.swift
#	Sources/Setup/DataStack.swift
#	Sources/Setup/StorageInterfaces/ICloudStore.swift
#	Sources/Setup/StorageInterfaces/LegacySQLiteStore.swift
#	Sources/Setup/StorageInterfaces/SQLiteStore.swift
#	Sources/Setup/StorageInterfaces/StorageInterface.swift
2016-09-27 18:55:37 +09:00
John Estropia
ed8c7b35e8 Reduce leaking (a little) on the workaround for NSFetchRequest.affectedStores ARC bug 2016-09-27 17:31:08 +09:00
John Rommel Estropia
4d2ebe4ea8 workaround #100 (NSFetchRequest.affectedStores ARC bug) 2016-09-27 02:39:28 +09:00
John Estropia
54be9d471c renamed ImportableObject and ImportableUniqueObject protocol methods to Swift 3 naming style 2016-09-21 12:00:48 +09:00
John Rommel Estropia
f18d62f643 travis yml update 2016-09-17 14:27:36 +09:00
John Rommel Estropia
af141d4a31 travis yml update 2016-09-17 14:26:33 +09:00
John Rommel Estropia
2da659a967 travis yml update 2016-09-17 14:14:29 +09:00
John Rommel Estropia
e5f162c5e1 minor readme edits 2016-09-17 13:59:04 +09:00
John Rommel Estropia
effa231719 fix travis 2016-09-17 13:37:00 +09:00
John Rommel Estropia
6cef8f4b4f updated travis yml 2016-09-17 13:23:56 +09:00
John Rommel Estropia
aa6bceaaf3 working for Swift 2.3! 2016-09-17 12:22:25 +09:00
John Rommel Estropia
0dbd05b172 version bump 2016-09-11 14:30:32 +09:00
John Rommel Estropia
243c4044ab fix bridging producing base abstract class instead of subclass concrete class 2016-09-11 14:30:25 +09:00
John Rommel Estropia
df835114cb ignore errors when deleting wal files 2016-09-10 22:57:45 +09:00
John Rommel Estropia
f99d3cc21a fix RecreateStoreOnModelMismatch option not working when an existing xcdatamodel gets updated without adding a new version 2016-09-10 22:51:33 +09:00
John Estropia
a51ed1a007 WIP: Renaming to meet Swift 3 API guidelines 2016-09-09 18:30:08 +09:00
John Estropia
e5245a0e5b user #keyPath() for keys in demo app and in unit tests 2016-09-09 17:05:55 +09:00
John Estropia
0fa2a23461 workaround for iOS 10 regression in "affectedStores" retain bug 2016-09-09 13:09:13 +09:00
John Estropia
3f28198552 Magical NSFetchedResultsController bugfix.... 2016-09-09 12:49:10 +09:00
John Rommel Estropia
4a34012d58 version bump 2016-09-08 00:40:58 +09:00
John Estropia
45690a29c6 Merge pull request #92 from ThibaultVlacich/develop
Add DEBUG flag to the Debug config
2016-09-07 19:01:19 +09:00
Thibault Vlacich
0d4d036a86 Add DEBUG flag to the Debug config 2016-09-07 10:43:43 +02:00
John Estropia
82de482191 WIP: broken generics 2016-09-06 20:16:46 +09:00
John Estropia
b502895d63 Merge branch 'develop' into swift3_develop
# Conflicts:
#	Sources/Internal/NotificationObserver.swift
2016-09-06 12:05:40 +09:00
John Estropia
ed0fdc76fe update podspec 2016-09-06 11:19:38 +09:00
John Estropia
58f4907575 Prevent retain cycles in NSManagedObjectContext (fixes #87) 2016-09-06 11:13:16 +09:00
John Estropia
0ba63c6e72 WIP: Xcode 8 beta 6 2016-09-06 09:57:28 +09:00
John Rommel Estropia
e9be711d4c WIP: demo app 2016-07-25 08:21:22 +09:00
John Rommel Estropia
db5b8ca702 Merge branch 'develop' into swift3_develop
# Conflicts:
#	Cartfile.resolved
#	Carthage/Checkouts/GCDKit
#	CoreStoreTests/ErrorTests.swift
#	Sources/Fetching and Querying/Concrete Clauses/Select.swift
#	Sources/ObjectiveC/CSError.swift
2016-07-22 00:47:03 +09:00
John Rommel Estropia
1950224863 version bump 2016-07-22 00:33:15 +09:00
John Rommel Estropia
f0cd288657 allow querying on relationship attributes (fixes #83) 2016-07-22 00:29:48 +09:00
John Rommel Estropia
2f39f9188b WIP: the great renaming 2016-07-21 23:12:24 +09:00
John Estropia
3344e42d7c version bump 2016-07-21 11:51:57 +09:00
John Estropia
e4b6c06401 fixed internal errors getting thrown as .Unknown instead of .InternalError (fixes #84) 2016-07-21 11:51:49 +09:00
John Rommel Estropia
872e69ddc6 WIP 2016-07-21 08:34:13 +09:00
John Rommel Estropia
f9e33101a0 WIP 2016-07-21 08:32:16 +09:00
John Rommel Estropia
0621c54868 WIP 2016-07-21 02:48:23 +09:00
John Rommel Estropia
a638620858 WIP 2016-07-21 02:45:42 +09:00
John Rommel Estropia
267c21063a WIP: segfault 2016-07-20 08:12:04 +09:00
John Estropia
7fc3ad2890 Tidy up, version bump 2016-07-14 19:59:15 +09:00
John Estropia
556f6d13b3 Merge pull request #81 from jannon/mark-app-extension-safe
Mark app extension safe
2016-07-14 19:41:55 +09:00
Jannon Frank
a088fe3817 mark iOS and tvOS safe for app extensions 2016-07-12 18:39:23 -07:00
Jannon Frank
c4391a8d0c Merge remote-tracking branch 'JohnEstropia/master' into upstream 2016-07-12 18:36:53 -07:00
232 changed files with 24916 additions and 14863 deletions

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "Carthage/Checkouts/GCDKit"]
path = Carthage/Checkouts/GCDKit
url = https://github.com/JohnEstropia/GCDKit.git

1
.swift-version Normal file
View File

@@ -0,0 +1 @@
3.1

View File

@@ -1,5 +1,5 @@
language: objective-c
osx_image: xcode7.3
osx_image: xcode8.3
sudo: false
git:
submodules: false
@@ -10,20 +10,22 @@ env:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
matrix:
- DESTINATION="OS=9.3,name=iPhone 6s" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.2,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES"
- DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="CoreStore iOS7" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES"
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.11 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator2.2 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator9.2 RUN_TESTS="YES" POD_LINT="NO"
- 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"
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.11/Carthage.pkg"
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.23.0/Carthage.pkg"
- sudo installer -pkg "Carthage.pkg" -target /
- rm "Carthage.pkg"
before_script:
@@ -36,8 +38,8 @@ script:
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
fi
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator9.3" -destination "OS=9.3,name=iPhone 6s" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator9.3" -destination "OS=9.3,name=iPhone 6s" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- if [ $POD_LINT == "YES" ]; then
pod lib lint --quick;
fi

View File

@@ -1 +0,0 @@
github "JohnEstropia/GCDKit" == 1.2.5

View File

@@ -1 +0,0 @@
github "JohnEstropia/GCDKit" "1.2.4"

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "CoreStore"
s.version = "2.0.0"
s.version = "4.0.5"
s.license = "MIT"
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
s.homepage = "https://github.com/JohnEstropia/CoreStore"
@@ -16,8 +16,5 @@ Pod::Spec.new do |s|
s.public_header_files = "Sources/**/*.h"
s.frameworks = "Foundation", "CoreData"
s.requires_arc = true
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '-D USE_FRAMEWORKS',
'GCC_PREPROCESSOR_DEFINITIONS' => 'USE_FRAMEWORKS=1' }
s.dependency "GCDKit", "1.2.5"
end
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG' }
end

File diff suppressed because it is too large Load Diff

View File

@@ -10,10 +10,10 @@
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "F347F55F-7F5C-4476-9148-6E902F06E4AD",
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
"8B2E522D57154DFA93A06982C36315ECBEA4FA97" : "CoreStoreLibraries\/GCDKit",
"4B60F1BCB491FF717C56441AE7783C74F417BE48" : "CoreStore"
"4B60F1BCB491FF717C56441AE7783C74F417BE48" : "CoreStore\/"
},
"DVTSourceControlWorkspaceBlueprintNameKey" : "CoreStore",
"DVTSourceControlWorkspaceBlueprintVersion" : 203,
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CoreStore.xcodeproj",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
{

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -11,8 +11,7 @@
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES"
hideIssues = "NO">
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A52F19C5C6DA005002A5"
@@ -26,8 +25,7 @@
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO"
hideIssues = "NO">
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
@@ -65,6 +63,11 @@
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</TestAction>
<LaunchAction

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -7,7 +7,4 @@
<FileRef
location = "group:CoreStoreDemo/CoreStoreDemo.xcodeproj">
</FileRef>
<FileRef
location = "group:Carthage/Checkouts/GCDKit/GCDKit.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -12,7 +12,6 @@
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */; };
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */; };
B5125C141B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */; };
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977D81B120B80003D50A5 /* ObserversViewController.swift */; };
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */; };
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977DE1B120F83003D50A5 /* MapKit.framework */; };
@@ -36,8 +35,6 @@
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */; };
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */; };
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */; };
B5E89ACD1C52929C003B04A9 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9241C202429008147CD /* GCDKit.framework */; };
B5E89ACE1C52929C003B04A9 /* GCDKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9241C202429008147CD /* GCDKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; };
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE25841B36E23C0000406B /* OrganismV1.swift */; };
@@ -54,7 +51,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
B5E89ACE1C52929C003B04A9 /* GCDKit.framework in Embed Frameworks */,
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
@@ -94,7 +90,6 @@
B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryingResultsViewController.swift; sourceTree = "<group>"; };
B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemo.xcdatamodel; sourceTree = "<group>"; };
B5BDC9211C202429008147CD /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B5BDC9241C202429008147CD /* GCDKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GCDKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OrganismTableViewCell.swift; path = "CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift"; sourceTree = SOURCE_ROOT; };
B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV2.xcdatamodel; sourceTree = "<group>"; };
B5EE25841B36E23C0000406B /* OrganismV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV1.swift; sourceTree = "<group>"; };
@@ -110,7 +105,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B5E89ACD1C52929C003B04A9 /* GCDKit.framework in Frameworks */,
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */,
B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */,
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */,
@@ -146,7 +140,6 @@
children = (
B52977E01B120F8A003D50A5 /* CoreLocation.framework */,
B5BDC9211C202429008147CD /* CoreStore.framework */,
B5BDC9241C202429008147CD /* GCDKit.framework */,
B52977DE1B120F83003D50A5 /* MapKit.framework */,
);
name = Frameworks;
@@ -272,11 +265,12 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = {
B54AAD481AF4D26E00848AE0 = {
CreatedOnToolsVersion = 6.3;
LastSwiftMigration = 0800;
};
};
};
@@ -336,7 +330,6 @@
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
B5125C141B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel in Sources */,
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
@@ -383,8 +376,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -428,8 +423,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -461,6 +458,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -473,6 +471,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
};
name = Release;
};

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,24 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B5D9E2ED1CA2C317007A9D52"
BuildableName = "CoreStore_iOS7.framework"
BlueprintName = "CoreStore iOS7"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
BlueprintIdentifier = "B54AAD481AF4D26E00848AE0"
BuildableName = "CoreStoreDemo.app"
BlueprintName = "CoreStoreDemo"
ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -42,24 +28,14 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A52F19C5C6DA005002A5"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
BlueprintIdentifier = "B54AAD481AF4D26E00848AE0"
BuildableName = "CoreStoreDemo.app"
BlueprintName = "CoreStoreDemo"
ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
@@ -75,15 +51,16 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B5D9E2ED1CA2C317007A9D52"
BuildableName = "CoreStore_iOS7.framework"
BlueprintName = "CoreStore iOS7"
ReferencedContainer = "container:CoreStore.xcodeproj">
BlueprintIdentifier = "B54AAD481AF4D26E00848AE0"
BuildableName = "CoreStoreDemo.app"
BlueprintName = "CoreStoreDemo"
ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
@@ -93,9 +70,19 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B54AAD481AF4D26E00848AE0"
BuildableName = "CoreStoreDemo.app"
BlueprintName = "CoreStoreDemo"
ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Release">
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"

View File

@@ -18,10 +18,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
application.statusBarStyle = .LightContent
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
application.statusBarStyle = .lightContent
return true
}
}

View File

@@ -1,39 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10112" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ni8-QF-XHB">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12113" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ni8-QF-XHB">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10083"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12078"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<customFonts key="customFonts">
<mutableArray key="AppleSDGothicNeo.ttc">
<array key="AppleSDGothicNeo.ttc">
<string>AppleSDGothicNeo-Regular</string>
</mutableArray>
<mutableArray key="HelveticaNeue.ttc">
<string>HelveticaNeue-Bold</string>
<string>HelveticaNeue-Bold</string>
</array>
<array key="HelveticaNeue.ttc">
<string>HelveticaNeue</string>
<string>HelveticaNeue</string>
</mutableArray>
<mutableArray key="HelveticaNeueLights.ttc">
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Bold</string>
</array>
<array key="HelveticaNeueLights.ttc">
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Thin</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
</mutableArray>
</array>
</customFonts>
<scenes>
<!--SNS Accounts-->
@@ -41,34 +30,34 @@
<objects>
<tableViewController id="AW4-lY-JNk" customClass="StackSetupDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="S3A-lm-AuA">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<view key="tableHeaderView" contentMode="scaleToFill" id="yud-WH-MPa">
<rect key="frame" x="0.0" y="64" width="600" height="150"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="150"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sns" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="czc-nd-es9">
<rect key="frame" x="20" y="20" width="560" height="26.5"/>
<rect key="frame" x="20" y="20" width="335" height="26.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="name" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1eh-91-O2N">
<rect key="frame" x="20" y="70" width="41" height="20.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="friends" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p2y-0T-hQs">
<rect key="frame" x="539.5" y="72" width="40.5" height="17"/>
<rect key="frame" x="314.5" y="72" width="40.5" height="17"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.20392156862745098" green="0.28627450980392155" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="1eh-91-O2N" firstAttribute="top" secondItem="czc-nd-es9" secondAttribute="bottom" constant="23.5" id="F6q-Jt-glI"/>
<constraint firstItem="p2y-0T-hQs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="1eh-91-O2N" secondAttribute="trailing" constant="20" id="GVS-6o-rmj"/>
@@ -82,24 +71,24 @@
</view>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="8b8-lM-Krq" detailTextLabel="hR1-Zb-BOk" style="IBUITableViewCellStyleValue1" id="dMt-nx-EO5">
<rect key="frame" x="0.0" y="236" width="600" height="44"/>
<rect key="frame" x="0.0" y="172" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dMt-nx-EO5" id="gdK-VV-zNb">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq">
<rect key="frame" x="15" y="13" width="28.5" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hR1-Zb-BOk">
<rect key="frame" x="533" y="13" width="52" height="19"/>
<rect key="frame" x="308" y="13" width="52" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -131,23 +120,23 @@
<viewControllerLayoutGuide type="bottom" id="t9A-zf-Iew"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="75P-2m-6cr">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="WUc-3Y-Quw">
<rect key="frame" x="0.0" y="324" width="600" height="276"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<rect key="frame" x="0.0" y="324" width="375" height="343"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="OrganismTableViewCell" id="WVb-th-o8c" customClass="OrganismTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="22" width="600" height="44"/>
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WVb-th-o8c" id="JBq-Ml-a9p">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OQf-Bd-Zze">
<rect key="frame" x="520" y="8" width="72" height="27.5"/>
<rect key="frame" x="295" y="8" width="72" height="27.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<inset key="contentEdgeInsets" minX="7" minY="0.0" maxX="7" maxY="0.0"/>
<state key="normal" title="mutate!"/>
@@ -156,9 +145,9 @@
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VZk-6K-4ut">
<rect key="frame" x="15" y="8" width="495" height="27.5"/>
<rect key="frame" x="15" y="8" width="270" height="27.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -184,42 +173,42 @@
</connections>
</tableView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XKA-Ub-c2X">
<rect key="frame" x="0.0" y="64" width="600" height="260"/>
<rect key="frame" x="0.0" y="64" width="375" height="260"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i7U-bW-juB" customClass="UIButton">
<rect key="frame" x="0.0" y="0.0" width="600" height="260"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="260"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Organism" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zxy-nY-P44">
<rect key="frame" x="20" y="90.5" width="560" height="26.5"/>
<rect key="frame" x="20" y="90.5" width="335" height="26.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="attributes" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6Ac-xl-ldZ">
<rect key="frame" x="20" y="131.5" width="560" height="20.5"/>
<rect key="frame" x="20" y="131.5" width="335" height="20.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="rAZ-eJ-sxy">
<rect key="frame" x="20" y="20" width="560" height="29"/>
<rect key="frame" x="20" y="20" width="335" height="29"/>
<segments>
<segment title="First"/>
<segment title="Second"/>
<segment title=""/>
</segments>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="segmentedControlValueChanged:" destination="iVv-Vc-nCL" eventType="valueChanged" id="RwG-kW-RPg"/>
</connections>
</segmentedControl>
<progressView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="869-wx-Odb">
<rect key="frame" x="20" y="68" width="560" height="2"/>
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="trackTintColor" white="1" alpha="0.20000000000000001" colorSpace="calibratedWhite"/>
<rect key="frame" x="20" y="68" width="335" height="2"/>
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="trackTintColor" red="1" green="1" blue="1" alpha="0.20000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
</progressView>
</subviews>
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="zxy-nY-P44" firstAttribute="leading" secondItem="i7U-bW-juB" secondAttribute="leading" constant="20" id="1u1-Tq-hRn"/>
<constraint firstItem="6Ac-xl-ldZ" firstAttribute="top" secondItem="zxy-nY-P44" secondAttribute="bottom" constant="14.5" id="39B-9l-O3g"/>
@@ -237,7 +226,7 @@
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="260" id="90R-Mf-iAB"/>
<constraint firstItem="i7U-bW-juB" firstAttribute="leading" secondItem="XKA-Ub-c2X" secondAttribute="leading" id="e9h-f4-c37"/>
@@ -246,7 +235,7 @@
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="XKA-Ub-c2X" secondAttribute="trailing" id="U0P-51-KT9"/>
<constraint firstAttribute="trailing" secondItem="WUc-3Y-Quw" secondAttribute="trailing" id="i7I-7B-97K"/>
@@ -276,31 +265,31 @@
<objects>
<tableViewController id="t0d-B0-B7U" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="50" sectionHeaderHeight="10" sectionFooterHeight="10" id="uHB-Yr-ujV">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<sections>
<tableViewSection id="wIP-Hn-YfF">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Q3n-Df-v1t" detailTextLabel="Hbn-cf-Y7m" style="IBUITableViewCellStyleSubtitle" id="AXm-KE-45G">
<rect key="frame" x="0.0" y="99" width="600" height="50"/>
<rect key="frame" x="0.0" y="35" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AXm-KE-45G" id="9te-Wx-hkf">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accounts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q3n-Df-v1t">
<rect key="frame" x="15" y="6" width="82" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Setting up multiple persistent store configurations" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Hbn-cf-Y7m">
<rect key="frame" x="15" y="30" width="263.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -310,24 +299,24 @@
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="vpt-cT-gMo" detailTextLabel="ou9-TZ-8bf" style="IBUITableViewCellStyleSubtitle" id="fsb-zw-8Ii">
<rect key="frame" x="0.0" y="149" width="600" height="50"/>
<rect key="frame" x="0.0" y="85" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fsb-zw-8Ii" id="Upm-AO-Fw3">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Colors" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vpt-cT-gMo">
<rect key="frame" x="15" y="6" width="56" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Observing list changes and single object changes" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ou9-TZ-8bf">
<rect key="frame" x="15" y="30" width="260.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -337,24 +326,24 @@
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="UbU-Kd-yrY" detailTextLabel="uP1-Jc-o9v" style="IBUITableViewCellStyleSubtitle" id="ekW-PJ-mbo">
<rect key="frame" x="0.0" y="199" width="600" height="50"/>
<rect key="frame" x="0.0" y="135" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekW-PJ-mbo" id="CYq-mg-PVS">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Placemarks" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UbU-Kd-yrY">
<rect key="frame" x="15" y="6" width="100.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Making changes with transactions" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uP1-Jc-o9v">
<rect key="frame" x="15" y="30" width="179" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -364,24 +353,24 @@
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="C8Y-0y-lEG" detailTextLabel="jZw-qE-0ws" style="IBUITableViewCellStyleSubtitle" id="ph1-8z-C1m">
<rect key="frame" x="0.0" y="249" width="600" height="50"/>
<rect key="frame" x="0.0" y="185" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ph1-8z-C1m" id="nNz-rd-ksg">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Time Zones" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="C8Y-0y-lEG">
<rect key="frame" x="15" y="6" width="101.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Fetching objects and raw values" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jZw-qE-0ws">
<rect key="frame" x="15" y="30" width="168.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -391,24 +380,24 @@
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="ZfY-Aq-Ykq" detailTextLabel="QzD-9b-k1j" style="IBUITableViewCellStyleSubtitle" id="wyK-rk-3tI">
<rect key="frame" x="0.0" y="299" width="600" height="50"/>
<rect key="frame" x="0.0" y="235" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wyK-rk-3tI" id="fLd-KK-QcW">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZfY-Aq-Ykq">
<rect key="frame" x="15" y="6" width="61" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Implementing a custom logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QzD-9b-k1j">
<rect key="frame" x="15" y="30" width="159" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -418,24 +407,24 @@
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hSG-mG-YBw" detailTextLabel="X9P-TQ-LYh" style="IBUITableViewCellStyleSubtitle" id="xTM-Cf-0if">
<rect key="frame" x="0.0" y="349" width="600" height="50"/>
<rect key="frame" x="0.0" y="285" width="375" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xTM-Cf-0if" id="DfO-BW-krd">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="49.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Evolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hSG-mG-YBw">
<rect key="frame" x="15" y="6" width="78.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Migrating and de-migrating stores" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X9P-TQ-LYh">
<rect key="frame" x="15" y="30" width="179.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -467,69 +456,69 @@
<viewControllerLayoutGuide type="bottom" id="aI4-O3-OCi"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="w8K-eN-RvU">
<rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
<rect key="frame" x="20" y="69.5" width="552" height="36.5"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfe-Yq-3Xa">
<rect key="frame" x="20" y="116" width="552" height="18"/>
<rect key="frame" x="16" y="149.5" width="343" height="18"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hue" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sgg-Md-Nf3">
<rect key="frame" x="20" y="154" width="74" height="18"/>
<rect key="frame" x="16" y="187.5" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Saturation" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rry-vh-bRK">
<rect key="frame" x="20" y="192" width="74" height="18"/>
<rect key="frame" x="16" y="225.5" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Brightness" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vTa-ly-eyO">
<rect key="frame" x="20" y="230" width="74" height="18"/>
<rect key="frame" x="16" y="263.5" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="359" translatesAutoresizingMaskIntoConstraints="NO" id="YQ6-fq-3Wb">
<rect key="frame" x="102" y="148" width="472" height="31"/>
<rect key="frame" x="98" y="181.5" width="263" height="31"/>
<connections>
<action selector="hueSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="9Hy-3h-llE"/>
</connections>
</slider>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="xXz-78-tAd">
<rect key="frame" x="102" y="186" width="472" height="31"/>
<rect key="frame" x="98" y="219.5" width="263" height="31"/>
<connections>
<action selector="saturationSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="qtU-ua-ZTc"/>
</connections>
</slider>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="hpy-2d-eOP">
<rect key="frame" x="102" y="224" width="472" height="31"/>
<rect key="frame" x="98" y="257.5" width="263" height="31"/>
<connections>
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
<rect key="frame" x="20" y="49" width="552" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="p4O-tf-dgt" firstAttribute="trailing" secondItem="w8K-eN-RvU" secondAttribute="trailingMargin" id="022-ll-1s1"/>
<constraint firstItem="vTa-ly-eyO" firstAttribute="top" secondItem="rry-vh-bRK" secondAttribute="bottom" constant="20" id="1hd-Ti-CnT"/>
@@ -591,23 +580,23 @@
<viewControllerLayoutGuide type="bottom" id="LNL-mj-D7l"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="6x3-vn-Egt">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
<rect key="frame" x="4" y="64" width="592" height="268"/>
<rect key="frame" x="0.0" y="64" width="375" height="301.5"/>
<connections>
<segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/>
</connections>
</containerView>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp">
<rect key="frame" x="4" y="332" width="592" height="268"/>
<rect key="frame" x="0.0" y="365.5" width="375" height="301.5"/>
<connections>
<segue destination="sll-yo-mBc" kind="embed" id="AAl-HS-dq2"/>
</connections>
</containerView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="6So-f3-4Gp" firstAttribute="top" secondItem="L5f-tW-lXf" secondAttribute="bottom" id="3m8-tj-Nd4"/>
<constraint firstAttribute="trailingMargin" secondItem="6So-f3-4Gp" secondAttribute="trailing" constant="-16" id="4L8-wZ-F59"/>
@@ -636,11 +625,11 @@
<navigationBar key="navigationBar" contentMode="scaleToFill" id="00L-5k-Eno">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<textAttributes key="titleTextAttributes">
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="24"/>
<color key="textColor" red="0.92549019607843142" green="0.94117647058823528" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</textAttributes>
</navigationBar>
<nil name="viewControllers"/>
@@ -657,19 +646,19 @@
<objects>
<tableViewController id="3AE-ED-0oj" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="DAz-BE-6Ca">
<rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="G3X-70-BCD" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="G3X-70-BCD" id="aT8-nz-i5l">
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF">
<rect key="frame" x="8" y="8" width="27" height="27"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" secondItem="uQX-PI-UWF" secondAttribute="height" multiplier="1:1" id="9qA-iN-Neb"/>
</constraints>
@@ -677,7 +666,7 @@
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HJC-5w-lIN">
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -716,20 +705,20 @@
<objects>
<tableViewController id="lCE-i6-UCT" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="Zba-8M-Zd7">
<rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="301.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="zSO-3e-OVq" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zSO-3e-OVq" id="cHA-by-n4b">
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH">
<rect key="frame" x="8" y="8" width="27" height="27"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" secondItem="5uq-Yi-XwH" secondAttribute="height" multiplier="1:1" id="oOe-HC-VyN"/>
</constraints>
@@ -737,7 +726,7 @@
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Zyu-PC-WmO">
<rect key="frame" x="45" y="8" width="34.5" height="27"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -780,11 +769,11 @@
<navigationBar key="navigationBar" contentMode="scaleToFill" id="6XA-6M-yvZ">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<textAttributes key="titleTextAttributes">
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</textAttributes>
</navigationBar>
<nil name="viewControllers"/>
@@ -805,17 +794,17 @@
<viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="k4s-iL-Krh">
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
<rect key="frame" x="0.0" y="0.0" width="600" height="536"/>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
<rect key="frame" x="0.0" y="0.0" width="375" height="536"/>
<connections>
<outlet property="delegate" destination="jPl-fH-NlD" id="Sjn-YC-haS"/>
</connections>
</mapView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="RZg-hi-T8O" firstAttribute="top" secondItem="V2U-0R-Ts0" secondAttribute="bottom" id="GcS-Jz-Wcm"/>
<constraint firstItem="V2U-0R-Ts0" firstAttribute="top" secondItem="k4s-iL-Krh" secondAttribute="top" id="S5Z-Da-V6J"/>
@@ -842,30 +831,30 @@
<viewControllerLayoutGuide type="bottom" id="Cwn-Jd-4Lr"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="n9M-Je-Dj0">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" alwaysBounceVertical="YES" indicatorStyle="white" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TpK-gX-CTN">
<rect key="frame" x="0.0" y="142" width="600" height="458"/>
<color key="backgroundColor" red="0.20392156862745098" green="0.28627450980392155" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.94509803921568625" green="0.7686274509803922" blue="0.058823529411764705" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<rect key="frame" x="0.0" y="142" width="375" height="525"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.92706394195556641" green="0.72759377956390381" blue="0.064024783670902252" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" name="AppleSDGothicNeo-Regular" family="Apple SD Gothic Neo" pointSize="15"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" momentary="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4iq-B4-k0p">
<rect key="frame" x="20" y="94" width="560" height="29"/>
<rect key="frame" x="20" y="94" width="335" height="29"/>
<segments>
<segment title="Log"/>
<segment title="Error"/>
<segment title="Assert"/>
</segments>
<color key="tintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="segmentedControlValueChanged:" destination="5yy-0N-QDU" eventType="valueChanged" id="2pp-Vt-2Os"/>
</connections>
</segmentedControl>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="4iq-B4-k0p" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" constant="20" id="6SM-eN-NxP"/>
<constraint firstItem="TpK-gX-CTN" firstAttribute="leading" secondItem="n9M-Je-Dj0" secondAttribute="leading" id="AAw-IG-taz"/>
@@ -901,11 +890,11 @@
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wJo-mp-1pS">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.74117647058823533" green="0.76470588235294112" blue="0.7803921568627451" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="barTintColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<textAttributes key="titleTextAttributes">
<fontDescription key="fontDescription" name="HelveticaNeue-Thin" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.74117647060000003" green="0.76470588240000004" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.68773996829986572" green="0.71417498588562012" blue="0.73246318101882935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</textAttributes>
</navigationBar>
<nil name="viewControllers"/>
@@ -926,15 +915,15 @@
<viewControllerLayoutGuide type="bottom" id="DlN-cN-JXd"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="eC3-ql-d2o">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="WGY-kX-mAx">
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<view key="tableHeaderView" contentMode="scaleToFill" id="iaH-1W-Sbo">
<rect key="frame" x="0.0" y="0.0" width="600" height="80"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="80"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bordered" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="YVj-dA-fyV">
@@ -943,13 +932,13 @@
<segment title="Fetch"/>
<segment title="Query"/>
</segments>
<color key="tintColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="segmentedControlValueChanged:" destination="qbj-MK-nIY" eventType="valueChanged" id="Wok-dl-uq7"/>
</connections>
</segmentedControl>
</subviews>
<color key="backgroundColor" white="1" alpha="0.80000000000000004" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YVj-dA-fyV" firstAttribute="leading" secondItem="iaH-1W-Sbo" secondAttribute="leading" constant="20" id="1dX-t7-dyR"/>
<constraint firstAttribute="centerY" secondItem="YVj-dA-fyV" secondAttribute="centerY" id="HXU-Z7-jfu"/>
@@ -958,17 +947,17 @@
</view>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="6db-P0-6Ms" style="IBUITableViewCellStyleDefault" id="vUr-WV-qur">
<rect key="frame" x="0.0" y="102" width="600" height="44"/>
<rect key="frame" x="0.0" y="102" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vUr-WV-qur" id="Vr0-hE-cn9">
<rect key="frame" x="0.0" y="0.0" width="567" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6db-P0-6Ms">
<rect key="frame" x="15" y="0.0" width="550" height="43.5"/>
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -981,7 +970,7 @@
</connections>
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="WGY-kX-mAx" firstAttribute="top" secondItem="dgu-PC-LiB" secondAttribute="bottom" id="0pS-cU-ibk"/>
<constraint firstAttribute="trailing" secondItem="WGY-kX-mAx" secondAttribute="trailing" id="NeY-g5-CaB"/>
@@ -1006,30 +995,30 @@
<objects>
<tableViewController id="tIs-pN-OgO" customClass="FetchingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="tVl-tT-UDk">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="RgX-yK-1L2" detailTextLabel="QZ4-A2-x4h" style="IBUITableViewCellStyleSubtitle" id="uBt-Iy-nWP">
<rect key="frame" x="0.0" y="100" width="600" height="60"/>
<rect key="frame" x="0.0" y="36" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="uBt-Iy-nWP" id="6SD-ur-9zp">
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RgX-yK-1L2">
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QZ4-A2-x4h">
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@@ -1052,30 +1041,30 @@
<objects>
<tableViewController id="o9D-Xm-13g" customClass="QueryingResultsViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="36" sectionFooterHeight="22" id="bMh-zR-xwu">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="Syt-QJ-KXg" detailTextLabel="yHS-dP-IKS" style="IBUITableViewCellStyleSubtitle" id="q7Q-aF-Ftl">
<rect key="frame" x="0.0" y="100" width="600" height="60"/>
<rect key="frame" x="0.0" y="36" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q7Q-aF-Ftl" id="fc3-eg-yes">
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Syt-QJ-KXg">
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="yHS-dP-IKS">
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.13079629838466644" green="0.184075728058815" blue="0.24594299495220184" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>

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

@@ -19,29 +19,27 @@ private struct Static {
SQLiteStore(
fileName: "TimeZoneDemo.sqlite",
configuration: "FetchingAndQueryingDemo",
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
dataStack.beginSynchronous { (transaction) -> Void in
transaction.deleteAll(From(TimeZone))
for name in NSTimeZone.knownTimeZoneNames() {
_ = try? dataStack.perform(
synchronous: { (transaction) in
let rawTimeZone = NSTimeZone(name: name)!
let cachedTimeZone = transaction.create(Into(TimeZone))
transaction.deleteAll(From<TimeZone>())
cachedTimeZone.name = rawTimeZone.name
cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? ""
cachedTimeZone.secondsFromGMT = Int32(rawTimeZone.secondsFromGMT)
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.daylightSavingTime
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
for name in NSTimeZone.knownTimeZoneNames {
let rawTimeZone = NSTimeZone(name: name)!
let cachedTimeZone = transaction.create(Into<TimeZone>())
cachedTimeZone.name = rawTimeZone.name
cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? ""
cachedTimeZone.secondsFromGMT = Int32(rawTimeZone.secondsFromGMT)
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
}
}
transaction.commitAndWait()
}
)
return dataStack
}()
}
@@ -53,7 +51,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
// MARK: UIViewController
override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
@@ -67,27 +65,27 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
let alert = UIAlertController(
title: "Fetch and Query Demo",
message: "This demo shows how to execute fetches and queries.\n\nEach menu item executes and displays a preconfigured fetch/query.",
preferredStyle: .Alert
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepareForSegue(segue, sender: sender)
super.prepare(for: segue, sender: sender)
if let indexPath = sender as? NSIndexPath {
if let indexPath = sender as? IndexPath {
switch segue.destinationViewController {
switch segue.destination {
case let controller as FetchingResultsViewController:
let item = self.fetchingItems[indexPath.row]
controller.setTimeZones(item.fetch(), title: item.title)
controller.set(timeZones: item.fetch(), title: item.title)
case let controller as QueryingResultsViewController:
let item = self.queryingItems[indexPath.row]
controller.setValue(item.query(), title: item.title)
controller.set(value: item.query(), title: item.title)
default:
break
@@ -98,14 +96,14 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
// MARK: UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch self.segmentedControl?.selectedSegmentIndex {
case Section.Fetching.rawValue?:
case Section.fetching.rawValue?:
return self.fetchingItems.count
case Section.Querying.rawValue?:
case Section.querying.rawValue?:
return self.queryingItems.count
default:
@@ -113,16 +111,16 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell")!
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")!
switch self.segmentedControl?.selectedSegmentIndex {
case Section.Fetching.rawValue?:
case Section.fetching.rawValue?:
cell.textLabel?.text = self.fetchingItems[indexPath.row].title
case Section.Querying.rawValue?:
case Section.querying.rawValue?:
cell.textLabel?.text = self.queryingItems[indexPath.row].title
default:
@@ -135,17 +133,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
switch self.segmentedControl?.selectedSegmentIndex {
case Section.Fetching.rawValue?:
self.performSegueWithIdentifier("FetchingResultsViewController", sender: indexPath)
case Section.fetching.rawValue?:
self.performSegue(withIdentifier: "FetchingResultsViewController", sender: indexPath)
case Section.Querying.rawValue?:
self.performSegueWithIdentifier("QueryingResultsViewController", sender: indexPath)
case Section.querying.rawValue?:
self.performSegue(withIdentifier: "QueryingResultsViewController", sender: indexPath)
default:
break
@@ -157,8 +155,8 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
private enum Section: Int {
case Fetching
case Querying
case fetching
case querying
}
private let fetchingItems = [
@@ -167,8 +165,8 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From(TimeZone),
OrderBy(.Ascending("name"))
From<TimeZone>(),
OrderBy(.ascending(#keyPath(TimeZone.name)))
)!
}
),
@@ -177,9 +175,9 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From(TimeZone),
Where("%K BEGINSWITH[c] %@", "name", "Asia"),
OrderBy(.Ascending("secondsFromGMT"))
From<TimeZone>(),
Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Asia"),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
)!
}
),
@@ -188,10 +186,10 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From(TimeZone),
Where("%K BEGINSWITH[c] %@", "name", "America")
|| Where("%K BEGINSWITH[c] %@", "name", "Europe"),
OrderBy(.Ascending("secondsFromGMT"))
From<TimeZone>(),
Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America")
|| Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Europe"),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
)!
}
),
@@ -200,9 +198,9 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From(TimeZone),
!Where("%K BEGINSWITH[c] %@", "name", "America"),
OrderBy(.Ascending("secondsFromGMT"))
From<TimeZone>(),
!Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America"),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)))
)!
}
),
@@ -211,9 +209,9 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
fetch: { () -> [TimeZone] in
return Static.timeZonesStack.fetchAll(
From(TimeZone),
From<TimeZone>(),
Where("hasDaylightSavingTime", isEqualTo: true),
OrderBy(.Ascending("name"))
OrderBy(.ascending(#keyPath(TimeZone.name)))
)!
}
)
@@ -222,60 +220,60 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
private let queryingItems = [
(
title: "Number of Time Zones",
query: { () -> AnyObject in
query: { () -> Any in
return Static.timeZonesStack.queryValue(
From(TimeZone),
Select<NSNumber>(.Count("name"))
From<TimeZone>(),
Select<NSNumber>(.count(#keyPath(TimeZone.name)))
)!
}
),
(
title: "Abbreviation For Tokyo's Time Zone",
query: { () -> AnyObject in
query: { () -> Any in
return Static.timeZonesStack.queryValue(
From(TimeZone),
Select<String>("abbreviation"),
Where("%K ENDSWITH[c] %@", "name", "Tokyo")
From<TimeZone>(),
Select<String>(#keyPath(TimeZone.abbreviation)),
Where("%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
)!
}
),
(
title: "All Abbreviations",
query: { () -> AnyObject in
query: { () -> Any in
return Static.timeZonesStack.queryAttributes(
From(TimeZone),
Select<NSDictionary>("name", "abbreviation"),
OrderBy(.Ascending("name"))
From<TimeZone>(),
Select<NSDictionary>(#keyPath(TimeZone.name), #keyPath(TimeZone.abbreviation)),
OrderBy(.ascending(#keyPath(TimeZone.name)))
)!
}
),
(
title: "Number of Countries per Time Zone",
query: { () -> AnyObject in
query: { () -> Any in
return Static.timeZonesStack.queryAttributes(
From(TimeZone),
Select<NSDictionary>(.Count("abbreviation"), "abbreviation"),
GroupBy("abbreviation"),
OrderBy(.Ascending("secondsFromGMT"), .Ascending("name"))
From<TimeZone>(),
Select<NSDictionary>(.count(#keyPath(TimeZone.abbreviation)), #keyPath(TimeZone.abbreviation)),
GroupBy(#keyPath(TimeZone.abbreviation)),
OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)), .ascending(#keyPath(TimeZone.name)))
)!
}
),
(
title: "Number of Countries with Summer Time",
query: { () -> AnyObject in
query: { () -> Any in
return Static.timeZonesStack.queryAttributes(
From(TimeZone),
From<TimeZone>(),
Select<NSDictionary>(
.Count("hasDaylightSavingTime", As: "numberOfCountries"),
"hasDaylightSavingTime"
.count(#keyPath(TimeZone.hasDaylightSavingTime), as: "numberOfCountries"),
#keyPath(TimeZone.hasDaylightSavingTime)
),
GroupBy("hasDaylightSavingTime"),
OrderBy(.Descending("hasDaylightSavingTime"))
GroupBy(#keyPath(TimeZone.hasDaylightSavingTime)),
OrderBy(.descending(#keyPath(TimeZone.hasDaylightSavingTime)))
)!
}
)
@@ -286,7 +284,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBOutlet dynamic weak var tableView: UITableView?
@IBAction dynamic func segmentedControlValueChanged(sender: AnyObject?) {
@IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
self.tableView?.reloadData()
}

View File

@@ -14,7 +14,7 @@ class FetchingResultsViewController: UITableViewController {
// MARK: Public
func setTimeZones(timeZones: [TimeZone]?, title: String) {
func set(timeZones: [TimeZone]?, title: String) {
self.timeZones += timeZones ?? []
self.sectionTitle = title
@@ -36,14 +36,14 @@ class FetchingResultsViewController: UITableViewController {
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.timeZones.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let timeZone = self.timeZones[indexPath.row]
cell.textLabel?.text = timeZone.name
@@ -55,7 +55,7 @@ class FetchingResultsViewController: UITableViewController {
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle
}

View File

@@ -12,23 +12,23 @@ class QueryingResultsViewController: UITableViewController {
// MARK: Public
func setValue(value: AnyObject?, title: String) {
func set(value: Any?, title: String) {
switch value {
case (let array as [AnyObject])?:
self.values = array.map { (item: AnyObject) -> (title: String, detail: String) in
case (let array as [Any])?:
self.values = array.map { (item: Any) -> (title: String, detail: String) in
(
title: item.description,
detail: String(reflecting: item.dynamicType)
title: String(describing: item),
detail: String(reflecting: type(of: item))
)
}
case let item?:
self.values = [
(
title: item.description,
detail: String(reflecting: item.dynamicType)
title: String(describing: item),
detail: String(reflecting: type(of: item))
)
]
@@ -55,14 +55,14 @@ class QueryingResultsViewController: UITableViewController {
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.values.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let value = self.values[indexPath.row]
@@ -75,7 +75,7 @@ class QueryingResultsViewController: UITableViewController {
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle
}

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,21 +10,21 @@ import UIKit
import CoreStore
private struct Static {
struct ColorsDemo {
enum Filter: String {
case All = "All Colors"
case Light = "Light Colors"
case Dark = "Dark Colors"
case all = "All Colors"
case light = "Light Colors"
case dark = "Dark Colors"
func next() -> Filter {
switch self {
case All: return .Light
case Light: return .Dark
case Dark: return .All
case .all: return .light
case .light: return .dark
case .dark: return .all
}
}
@@ -32,35 +32,51 @@ private struct Static {
switch self {
case .All: return Where(true)
case .Light: return Where("brightness >= 0.9")
case .Dark: return Where("brightness <= 0.4")
case .all: return Where(true)
case .light: return Palette.where({ $0.brightness >= 0.9 })
case .dark: return Palette.where({ $0.brightness <= 0.4 })
}
}
}
static var filter = Filter.All {
static var filter = Filter.all {
didSet {
self.palettes.refetch(self.filter.whereClause())
self.palettes.refetch(
self.filter.whereClause(),
Palette.orderBy(ascending: { $0.hue })
)
}
}
static let palettes: ListMonitor<Palette> = {
try! CoreStore.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
configuration: "ObservingDemo",
localStorageOptions: .RecreateStoreOnModelMismatch
static let stack: DataStack = {
return DataStack(
CoreStoreSchema(
modelVersion: "ColorsDemo",
entities: [
Entity<Palette>("Palette"),
],
versionLock: [
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
]
)
)
}()
static let palettes: ListMonitor<Palette> = {
return CoreStore.monitorSectionedList(
From(Palette),
SectionBy("colorName"),
OrderBy(.Ascending("hue"))
try! ColorsDemo.stack.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
return ColorsDemo.stack.monitorSectionedList(
From<Palette>(),
SectionBy(Palette.keyPath({ $0.colorName })),
Palette.orderBy(ascending: { $0.hue })
)
}()
}
@@ -74,7 +90,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
deinit {
Static.palettes.removeObserver(self)
ColorsDemo.palettes.removeObserver(self)
}
@@ -86,23 +102,23 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem(),
self.editButtonItem,
UIBarButtonItem(
barButtonSystemItem: .Trash,
barButtonSystemItem: .trash,
target: self,
action: #selector(self.resetBarButtonItemTouched(_:))
)
]
let filterBarButton = UIBarButtonItem(
title: Static.filter.rawValue,
style: .Plain,
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .Add,
barButtonSystemItem: .add,
target: self,
action: #selector(self.addBarButtonItemTouched(_:))
),
@@ -110,16 +126,16 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
]
self.filterBarButton = filterBarButton
Static.palettes.addObserver(self)
ColorsDemo.palettes.addObserver(self)
self.setTableEnabled(!Static.palettes.isPendingRefetch)
self.setTable(enabled: !ColorsDemo.palettes.isPendingRefetch)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepareForSegue(segue, sender: sender)
super.prepare(for: segue, sender: sender)
switch (segue.identifier, segue.destinationViewController, sender) {
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as Palette):
destinationViewController.palette = palette
@@ -132,21 +148,21 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
// MARK: UITableViewDataSource
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
override func numberOfSections(in tableView: UITableView) -> Int {
return Static.palettes.numberOfSections()
return ColorsDemo.palettes.numberOfSections()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Static.palettes.numberOfObjectsInSection(section)
return ColorsDemo.palettes.numberOfObjectsInSection(section)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("PaletteTableViewCell") as! PaletteTableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
let palette = Static.palettes[indexPath]
let palette = ColorsDemo.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
@@ -156,103 +172,106 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
self.performSegueWithIdentifier(
"ObjectObserverDemoViewController",
sender: Static.palettes[indexPath]
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes[indexPath]
)
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .Delete:
let palette = Static.palettes[indexPath]
CoreStore.beginAsynchronous{ (transaction) -> Void in
transaction.delete(palette)
transaction.commit { (result) -> Void in }
}
case .delete:
let palette = ColorsDemo.palettes[indexPath]
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.delete(palette)
},
completion: { _ in }
)
default:
break
}
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return Static.palettes.sectionInfoAtIndex(section).name
return ColorsDemo.palettes.sectionInfoAtIndex(section).name
}
// MARK: ListObserver
func listMonitorWillChange(monitor: ListMonitor<Palette>) {
func listMonitorWillChange(_ monitor: ListMonitor<Palette>) {
self.tableView.beginUpdates()
}
func listMonitorDidChange(monitor: ListMonitor<Palette>) {
func listMonitorDidChange(_ monitor: ListMonitor<Palette>) {
self.tableView.endUpdates()
}
func listMonitorWillRefetch(monitor: ListMonitor<Palette>) {
func listMonitorWillRefetch(_ monitor: ListMonitor<Palette>) {
self.setTableEnabled(false)
self.setTable(enabled: false)
}
func listMonitorDidRefetch(monitor: ListMonitor<Palette>) {
func listMonitorDidRefetch(_ monitor: ListMonitor<Palette>) {
self.filterBarButton?.title = Static.filter.rawValue
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.tableView.reloadData()
self.setTableEnabled(true)
self.setTable(enabled: true)
}
// MARK: ListObjectObserver
func listMonitor(monitor: ListMonitor<Palette>, didInsertObject object: Palette, toIndexPath indexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<Palette>, didInsertObject object: Palette, toIndexPath indexPath: IndexPath) {
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
self.tableView.insertRows(at: [indexPath], with: .automatic)
}
func listMonitor(monitor: ListMonitor<Palette>, didDeleteObject object: Palette, fromIndexPath indexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<Palette>, didDeleteObject object: Palette, fromIndexPath indexPath: IndexPath) {
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
func listMonitor(monitor: ListMonitor<Palette>, didUpdateObject object: Palette, atIndexPath indexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<Palette>, didUpdateObject object: Palette, atIndexPath indexPath: IndexPath) {
if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? PaletteTableViewCell {
if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell {
let palette = Static.palettes[indexPath]
let palette = ColorsDemo.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
}
}
func listMonitor(monitor: ListMonitor<Palette>, didMoveObject object: Palette, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<Palette>, didMoveObject object: Palette, fromIndexPath: IndexPath, toIndexPath: IndexPath) {
self.tableView.deleteRowsAtIndexPaths([fromIndexPath], withRowAnimation: .Automatic)
self.tableView.insertRowsAtIndexPaths([toIndexPath], withRowAnimation: .Automatic)
self.tableView.deleteRows(at: [fromIndexPath], with: .automatic)
self.tableView.insertRows(at: [toIndexPath], with: .automatic)
}
// MARK: ListSectionObserver
func listMonitor(monitor: ListMonitor<Palette>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) {
func listMonitor(_ monitor: ListMonitor<Palette>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) {
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic)
self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .automatic)
}
func listMonitor(monitor: ListMonitor<Palette>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
func listMonitor(_ monitor: ListMonitor<Palette>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic)
self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .automatic)
}
@@ -260,43 +279,46 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
private var filterBarButton: UIBarButtonItem?
@IBAction private dynamic func resetBarButtonItemTouched(sender: AnyObject?) {
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
CoreStore.beginAsynchronous { (transaction) -> Void in
transaction.deleteAll(From(Palette))
transaction.commit()
}
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.deleteAll(From<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func filterBarButtonItemTouched(sender: AnyObject?) {
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
Static.filter = Static.filter.next()
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(sender: AnyObject?) {
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
CoreStore.beginAsynchronous { (transaction) -> Void in
let palette = transaction.create(Into(Palette))
palette.setInitialValues()
transaction.commit()
}
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
},
completion: { _ in }
)
}
private func setTableEnabled(enabled: Bool) {
private func setTable(enabled: Bool) {
UIView.animateWithDuration(
0.2,
UIView.animate(
withDuration: 0.2,
delay: 0,
options: .BeginFromCurrentState,
options: .beginFromCurrentState,
animations: { () -> Void in
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
tableView.userInteractionEnabled = enabled
tableView.isUserInteractionEnabled = enabled
}
},
completion: nil

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("hue"))) {
if let palette = ColorsDemo.stack.fetchOne(From<Palette>(), Palette.orderBy(ascending: { $0.hue })) {
self.monitor = CoreStore.monitorObject(palette)
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
else {
CoreStore.beginSynchronous { (transaction) -> Void in
let palette = transaction.create(Into(Palette))
palette.setInitialValues()
transaction.commitAndWait()
}
_ = try? ColorsDemo.stack.perform(
synchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
}
)
let palette = CoreStore.fetchOne(From(Palette), OrderBy(.Ascending("hue")))!
self.monitor = CoreStore.monitorObject(palette)
let palette = ColorsDemo.stack.fetchOne(From<Palette>(), Palette.orderBy(ascending: { $0.hue }))!
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
super.init(coder: aDecoder)
@@ -85,24 +85,24 @@ 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<KeyPath>) {
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
}
func objectMonitor(monitor: ObjectMonitor<Palette>, didDeleteObject object: Palette) {
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didDeleteObject object: Palette) {
self.navigationItem.rightBarButtonItem?.enabled = false
self.navigationItem.rightBarButtonItem?.isEnabled = false
self.colorNameLabel?.alpha = 0.3
self.colorView?.alpha = 0.3
self.hsbLabel?.text = "Deleted"
self.hsbLabel?.textColor = UIColor.redColor()
self.hsbLabel?.textColor = UIColor.red
self.hueSlider?.enabled = false
self.saturationSlider?.enabled = false
self.brightnessSlider?.enabled = false
self.hueSlider?.isEnabled = false
self.saturationSlider?.isEnabled = false
self.brightnessSlider?.isEnabled = false
}
@@ -118,57 +118,65 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
@IBOutlet weak var saturationSlider: UISlider?
@IBOutlet weak var brightnessSlider: UISlider?
@IBAction dynamic func hueSliderValueDidChange(sender: AnyObject?) {
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
let hue = self.hueSlider?.value ?? 0
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
if let palette = transaction.edit(self?.monitor?.object) {
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
palette.hue = Int32(hue)
transaction.commit()
}
}
if let palette = transaction.edit(self?.monitor?.object) {
palette.hue .= Int(hue)
}
},
completion: { _ in }
)
}
@IBAction dynamic func saturationSliderValueDidChange(sender: AnyObject?) {
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
let saturation = self.saturationSlider?.value ?? 0
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
if let palette = transaction.edit(self?.monitor?.object) {
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
palette.saturation = saturation
transaction.commit()
}
}
if let palette = transaction.edit(self?.monitor?.object) {
palette.saturation .= saturation
}
},
completion: { _ in }
)
}
@IBAction dynamic func brightnessSliderValueDidChange(sender: AnyObject?) {
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
let brightness = self.brightnessSlider?.value ?? 0
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
if let palette = transaction.edit(self?.monitor?.object) {
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
palette.brightness = brightness
transaction.commit()
}
}
if let palette = transaction.edit(self?.monitor?.object) {
palette.brightness .= brightness
}
},
completion: { _ in }
)
}
@IBAction dynamic func deleteBarButtonTapped(sender: AnyObject?) {
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in
transaction.delete(self?.monitor?.object)
transaction.commit()
}
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
transaction.delete(self?.monitor?.object)
},
completion: { _ in }
)
}
func reloadPaletteInfo(palette: Palette, changedKeys: Set<String>?) {
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
self.colorNameLabel?.text = palette.colorName
self.colorNameLabel?.text = palette.colorName.value
let color = palette.color
self.colorNameLabel?.textColor = color
@@ -176,17 +184,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
self.hsbLabel?.text = palette.colorText
if changedKeys == nil || changedKeys?.contains("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("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("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

@@ -15,16 +15,16 @@ class ObserversViewController: UIViewController {
// MARK: UIViewController
override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Observers Demo",
message: "This demo shows how to observe changes to a list of objects. The top and bottom view controllers both observe a single shared \"ListMonitor\" instance.\n\nTap on a row to see how to observe changes made to a single object using a \"ObjectMonitor\".",
preferredStyle: .Alert
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}

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")
let saturation = Value.Required<Float>("saturation")
let brightness = Value.Required<Float>("brightness")
let colorName = Value.Optional<String>(
"colorName",
isTransient: true,
customGetter: Palette.getCachedColorName
)
private static func getCachedColorName(_ instance: Palette, _ getValue: () -> String?) -> String? {
get {
if let colorName = getValue() {
let KVCKey = "colorName"
if let colorName = self.accessValueForKVCKey(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 instance.hue.value % 360 {
self.setValue(newValue, forKVCKey: "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"
}
instance.colorName.primitiveValue = 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

@@ -8,7 +8,6 @@
import UIKit
import CoreStore
import GCDKit
// MARK: - CustomLoggerViewController
@@ -34,47 +33,47 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
CoreStore.logger = self
}
override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Logger Demo",
message: "This demo shows how to plug-in any logging framework to CoreStore.\n\nThe view controller implements CoreStoreLogger and appends all logs to the text view.",
preferredStyle: .Alert
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: CoreStoreLogger
func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
GCDQueue.Main.async { [weak self] in
DispatchQueue.main.async { [weak self] in
let levelString: String
switch level {
case .Trace: levelString = "Trace"
case .Notice: levelString = "Notice"
case .Warning: levelString = "Warning"
case .Fatal: levelString = "Fatal"
case .trace: levelString = "Trace"
case .notice: levelString = "Notice"
case .warning: levelString = "Warning"
case .fatal: levelString = "Fatal"
}
self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n")
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n")
}
}
func log(error error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
GCDQueue.Main.async { [weak self] in
DispatchQueue.main.async { [weak self] in
self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n")
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n")
}
}
func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
if condition() {
@@ -82,9 +81,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
}
let messageString = message()
GCDQueue.Main.async { [weak self] in
DispatchQueue.main.async { [weak self] in
self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(messageString)\n\n")
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(messageString)\n\n")
}
}
@@ -94,15 +93,14 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
@IBOutlet dynamic weak var textView: UITextView?
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBAction dynamic func segmentedControlValueChanged(sender: AnyObject?) {
@IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
switch self.segmentedControl?.selectedSegmentIndex {
case 0?:
self.dataStack.beginAsynchronous { (transaction) -> Void in
transaction.create(Into(Palette))
}
let request = NSFetchRequest<NSFetchRequestResult>()
Where(true).applyToFetchRequest(request)
Where(false).applyToFetchRequest(request)
case 1?:
_ = try? dataStack.addStorageAndWait(
@@ -113,10 +111,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
)
case 2?:
self.dataStack.beginAsynchronous { (transaction) -> Void in
DispatchQueue.global(qos: .background).async {
transaction.commit()
transaction.commit()
_ = self.dataStack.fetchOne(From<Place>())
}
default:

View File

@@ -12,7 +12,7 @@ import CoreStore
// MARK: - MigrationsDemoViewController
class MigrationsDemoViewController: UIViewController {
class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewDataSource, UITableViewDelegate {
// MARK: UIViewController
@@ -22,31 +22,31 @@ class MigrationsDemoViewController: UIViewController {
if let segmentedControl = self.segmentedControl {
for (index, model) in self.models.enumerate() {
for (index, model) in self.models.enumerated() {
segmentedControl.setTitle(
model.label,
forSegmentAtIndex: index
forSegmentAt: index
)
}
}
self.setDataStack(nil, model: nil, scrollToSelection: false)
self.set(dataStack: nil, model: nil, scrollToSelection: false)
}
override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Migrations Demo",
message: "This demo shows how to run progressive migrations and how to support multiple model versions in a single project.\n\nThe persistent store contains 10000 organisms, which gain/lose properties when the migration evolves/devolves them.\n\nYou can use the \"mutate\" button to change an organism's properties then migrate to a different model to see how its value gets affected.",
preferredStyle: .Alert
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
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
@@ -60,7 +60,7 @@ class MigrationsDemoViewController: UIViewController {
}
for model in models {
if model.version == storeVersion {
if model.schemaHistory.currentModelVersion == storeVersion {
return model
}
@@ -72,32 +72,121 @@ class MigrationsDemoViewController: UIViewController {
self.selectModelVersion(modelMetadata)
}
// MARK: ListObserver
func listMonitorWillChange(_ monitor: ListMonitor<NSManagedObject>) { }
func listMonitorDidChange(_ monitor: ListMonitor<NSManagedObject>) {
if self.lastSelectedIndexPath == nil,
let numberOfObjectsInSection = self.listMonitor?.numberOfObjectsInSection(0),
numberOfObjectsInSection > 0 {
self.tableView?.reloadData()
self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: false)
}
else {
self.updateDisplay(reloadData: true, scrollToSelection: true, animated: true)
}
}
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
self.listMonitorDidChange(monitor)
}
// MARK: UITableViewDataSource
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.listMonitor?.numberOfObjectsInSection(0) ?? 0
}
@objc dynamic func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OrganismTableViewCell", for: indexPath) as! OrganismTableViewCell
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
cell.dnaLabel?.text = "DNA: \(dna)"
cell.mutateButtonHandler = { [weak self] _ -> Void in
guard let `self` = self,
let dataStack = self.dataStack,
let organism = self.listMonitor?[indexPath] else {
return
}
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
self.setEnabled(false)
dataStack.perform(
asynchronous: { (transaction) in
let organism = transaction.edit(organism) as! OrganismProtocol
organism.mutate()
},
completion: { [weak self] _ in
self?.setEnabled(true)
}
)
}
return cell
}
// MARK: UITableViewDelegate
@objc dynamic func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
}
// MARK: Private
private typealias ModelMetadata = (label: String, version: String, entityType: AnyClass, migrationChain: MigrationChain)
private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
private let models: [ModelMetadata] = [
(
label: "Model V1",
version: "MigrationDemo",
entityType: OrganismV1.self,
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
),
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
)
),
(
label: "Model V2",
version: "MigrationDemoV2",
entityType: OrganismV2.self,
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
),
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
)
),
(
label: "Model V3",
version: "MigrationDemoV3",
entityType: OrganismV3.self,
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
),
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
)
]
@@ -113,13 +202,13 @@ class MigrationsDemoViewController: UIViewController {
return self._dataStack
}
private var _lastSelectedIndexPath: NSIndexPath?
private var lastSelectedIndexPath: NSIndexPath? {
private var _lastSelectedIndexPath: IndexPath?
private var lastSelectedIndexPath: IndexPath? {
return self._lastSelectedIndexPath
}
private func setSelectedIndexPath(indexPath: NSIndexPath, scrollToSelection: Bool) {
private func setSelectedIndexPath(_ indexPath: IndexPath, scrollToSelection: Bool) {
self._lastSelectedIndexPath = indexPath
self.updateDisplay(reloadData: false, scrollToSelection: scrollToSelection, animated: true)
@@ -132,7 +221,7 @@ class MigrationsDemoViewController: UIViewController {
@IBOutlet private dynamic weak var progressView: UIProgressView?
@IBOutlet private dynamic weak var tableView: UITableView?
@IBAction private dynamic func segmentedControlValueChanged(sender: AnyObject?) {
@IBAction private dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
guard let index = self.segmentedControl?.selectedSegmentIndex else {
@@ -142,23 +231,46 @@ class MigrationsDemoViewController: UIViewController {
self.selectModelVersion(self.models[index])
}
private func selectModelVersion(model: ModelMetadata) {
private func selectModelVersion(_ model: ModelMetadata) {
if self.dataStack?.modelVersion == model.version {
if self.dataStack?.modelVersion == model.schemaHistory.currentModelVersion {
return
}
self.setDataStack(nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
let dataStack = DataStack(
modelName: "MigrationDemo",
migrationChain: model.migrationChain
)
let dataStack = DataStack(schemaHistory: model.schemaHistory)
self.setEnabled(false)
let progress = dataStack.addStorage(
SQLiteStore(fileName: "MigrationDemo.sqlite"),
SQLiteStore(
fileName: "MigrationDemo.sqlite",
migrationMappingProviders: [
CustomSchemaMappingProvider(
from: "MigrationDemoV3",
to: "MigrationDemoV2",
entityMappings: [
.transformEntity(
sourceEntity: "Organism",
destinationEntity: "Organism",
transformer: { (source, createDestination) in
let destination = createDestination()
destination.enumerateAttributes { (attribute, sourceAttribute) in
if let sourceAttribute = sourceAttribute {
destination[attribute] = source[sourceAttribute]
}
}
destination["numberOfFlippers"] = source["numberOfLimbs"]
}
)
]
)
]
),
completion: { [weak self] (result) -> Void in
guard let `self` = self else {
@@ -166,18 +278,17 @@ class MigrationsDemoViewController: UIViewController {
return
}
guard case .Success = result else {
guard case .success = result else {
self.setEnabled(true)
return
}
self.setDataStack(dataStack, model: model, scrollToSelection: true)
self.set(dataStack: dataStack, model: model, scrollToSelection: true)
let count = dataStack.queryValue(
From(model.entityType),
Select<Int>(.Count("dna"))
)
Select<Int>(.count(#keyPath(OrganismV1.dna))))!
if count > 0 {
self.setEnabled(true)
@@ -186,25 +297,26 @@ class MigrationsDemoViewController: UIViewController {
for i: Int64 in 0 ..< 20 {
dataStack.beginAsynchronous { (transaction) -> Void in
for j: Int64 in 0 ..< 500 {
dataStack.perform(
asynchronous: { (transaction) in
let organism = transaction.create(Into(model.entityType)) as! OrganismProtocol
organism.dna = (i * 500) + j + 1
organism.mutate()
}
transaction.commit()
}
for j: Int64 in 0 ..< 500 {
let organism = transaction.create(Into(model.entityType)) as! OrganismProtocol
organism.dna = (i * 500) + j + 1
organism.mutate()
}
},
completion: { _ in }
)
}
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in
transaction.commit { _ in
dataStack.perform(
asynchronous: { _ in },
completion: { [weak self] _ in
self?.setEnabled(true)
}
}
)
}
}
)
@@ -218,39 +330,45 @@ class MigrationsDemoViewController: UIViewController {
}
}
private func setEnabled(enabled: Bool) {
private func setEnabled(_ enabled: Bool) {
UIView.animateWithDuration(
0.2,
UIView.animate(
withDuration: 0.2,
delay: 0,
options: .BeginFromCurrentState,
options: .beginFromCurrentState,
animations: { () -> Void in
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItem?.enabled = enabled
navigationItem.rightBarButtonItem?.enabled = enabled
navigationItem.leftBarButtonItem?.isEnabled = enabled
navigationItem.rightBarButtonItem?.isEnabled = enabled
navigationItem.hidesBackButton = !enabled
self.segmentedControl?.enabled = enabled
self.segmentedControl?.isEnabled = enabled
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
tableView.userInteractionEnabled = enabled
tableView.isUserInteractionEnabled = enabled
}
},
completion: nil
)
}
private func setDataStack(dataStack: DataStack?, model: ModelMetadata?, scrollToSelection: Bool) {
private func set(dataStack: DataStack?, model: ModelMetadata?, scrollToSelection: Bool) {
if let dataStack = dataStack, let model = model {
self.segmentedControl?.selectedSegmentIndex = self.models.map { $0.version }.indexOf(model.version)!
self.segmentedControl?.selectedSegmentIndex = self.models
.index(
where: { (_, _, schemaHistory) -> Bool in
schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
}
)!
self._dataStack = dataStack
let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.Descending("dna")))
let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna")))
listMonitor.addObserver(self)
self._listMonitor = listMonitor
@@ -258,7 +376,7 @@ class MigrationsDemoViewController: UIViewController {
if listMonitor.numberOfObjectsInSection(0) > 0 {
self.setSelectedIndexPath(NSIndexPath(forRow: 0, inSection: 0), scrollToSelection: true)
self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: true)
}
}
}
@@ -272,14 +390,14 @@ class MigrationsDemoViewController: UIViewController {
self.updateDisplay(reloadData: true, scrollToSelection: scrollToSelection, animated: false)
}
private func reloadTableHeaderWithProgress(progress: NSProgress) {
private func reloadTableHeaderWithProgress(_ progress: Progress) {
self.progressView?.setProgress(Float(progress.fractionCompleted), animated: true)
self.titleLabel?.text = "Migrating: \(progress.localizedDescription)"
self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription)"
self.titleLabel?.text = "Migrating: \(progress.localizedDescription ?? "")"
self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription ?? "")"
}
private func updateDisplay(reloadData reloadData: Bool, scrollToSelection: Bool, animated: Bool) {
private func updateDisplay(reloadData: Bool, scrollToSelection: Bool, animated: Bool) {
var lines = [String]()
var organismType = ""
@@ -287,14 +405,14 @@ class MigrationsDemoViewController: UIViewController {
for property in organism.entity.properties {
let value: AnyObject = organism.valueForKey(property.name) ?? NSNull()
let value = organism.value(forKey: property.name) ?? NSNull()
lines.append("\(property.name): \(value)")
}
organismType = organism.entity.managedObjectClassName
}
self.titleLabel?.text = organismType
self.organismLabel?.text = lines.joinWithSeparator("\n")
self.organismLabel?.text = lines.joined(separator: "\n")
self.progressView?.progress = 0
self.headerContainer?.setNeedsLayout()
@@ -311,87 +429,13 @@ class MigrationsDemoViewController: UIViewController {
tableView.layoutIfNeeded()
if let indexPath = self.lastSelectedIndexPath where indexPath.row < tableView.numberOfRowsInSection(0) {
if let indexPath = self.lastSelectedIndexPath,
indexPath.row < tableView.numberOfRows(inSection: 0) {
tableView.selectRowAtIndexPath(indexPath,
tableView.selectRow(at: indexPath,
animated: scrollToSelection && animated,
scrollPosition: scrollToSelection ? .Middle : .None
scrollPosition: scrollToSelection ? .middle : .none
)
}
}
}
// MARK: - MigrationsDemoViewController: ListObserver
extension MigrationsDemoViewController: ListObserver {
// MARK: ListObserver
func listMonitorWillChange(monitor: ListMonitor<NSManagedObject>) { }
func listMonitorDidChange(monitor: ListMonitor<NSManagedObject>) {
if self.lastSelectedIndexPath == nil && self.listMonitor?.numberOfObjectsInSection(0) > 0 {
self.tableView?.reloadData()
self.setSelectedIndexPath(NSIndexPath(forRow: 0, inSection: 0), scrollToSelection: false)
}
else {
self.updateDisplay(reloadData: true, scrollToSelection: true, animated: true)
}
}
}
// MARK: - MigrationsDemoViewController: UITableViewDataSource, UITableViewDelegate
extension MigrationsDemoViewController: UITableViewDataSource, UITableViewDelegate {
// MARK: UITableViewDataSource
@objc dynamic func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.listMonitor?.numberOfObjectsInSection(0) ?? 0
}
@objc dynamic func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("OrganismTableViewCell", forIndexPath: indexPath) as! OrganismTableViewCell
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
cell.dnaLabel?.text = "DNA: \(dna)"
cell.mutateButtonHandler = { [weak self] _ -> Void in
guard let `self` = self,
let dataStack = self.dataStack,
let organism = self.listMonitor?[indexPath] else {
return
}
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
self.setEnabled(false)
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in
let organism = transaction.edit(organism) as! OrganismProtocol
organism.mutate()
transaction.commit { _ -> Void in
self?.setEnabled(true)
}
}
}
return cell
}
// MARK: UITableViewDelegate
@objc dynamic func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
}
}

View File

@@ -13,4 +13,4 @@ protocol OrganismProtocol: class {
var dna: Int64 { get set }
func mutate()
}
}

View File

@@ -15,7 +15,7 @@ class OrganismTableViewCell: UITableViewCell {
var mutateButtonHandler: (() -> Void)?
@IBAction dynamic func mutateButtonTouchUpInside(sender: UIButton?) {
@IBAction dynamic func mutateButtonTouchUpInside(_ sender: UIButton?) {
self.mutateButtonHandler?()
}

View File

@@ -10,14 +10,20 @@ import CoreData
class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy {
override func createDestinationInstancesForSourceInstance(sInstance: NSManagedObject, entityMapping mapping: NSEntityMapping, manager: NSMigrationManager) throws {
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
try super.createDestinationInstancesForSourceInstance(sInstance, entityMapping: mapping, manager: manager)
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
for dInstance in manager.destinationInstancesForEntityMappingNamed(mapping.name, sourceInstances: [sInstance]) {
for dInstance in manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]) {
dInstance.setValue(false, forKey: "hasVertebrae")
dInstance.setValue(sInstance.valueForKey("numberOfFlippers"), forKey: "numberOfLimbs")
dInstance.setValue(
false,
forKey: #keyPath(OrganismV3.hasVertebrae)
)
dInstance.setValue(
sInstance.value(forKey: #keyPath(OrganismV2.numberOfFlippers)),
forKey: #keyPath(OrganismV3.numberOfLimbs)
)
}
}
}

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" standalone="no"?>
<?xml version="1.0"?>
<!DOCTYPE database SYSTEM "file:///System/Library/DTDs/CoreData.dtd">
<database>
@@ -10,7 +10,7 @@
<plist version="1.0">
<dict>
<key>NSPersistenceFrameworkVersion</key>
<integer>526</integer>
<integer>754</integer>
<key>NSStoreModelVersionHashes</key>
<dict>
<key>XDDevAttributeMapping</key>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14E46" minimumToolsVersion="Xcode 4.3">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV1" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" syncable="YES"/>
<attribute name="hasHead" optional="YES" attributeType="Boolean" syncable="YES"/>
<attribute name="hasTail" optional="YES" attributeType="Boolean" syncable="YES"/>
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="90"/>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14E46" minimumToolsVersion="Xcode 4.3">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV2" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" syncable="YES"/>
<attribute name="numberOfFlippers" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="numberOfFlippers" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="105"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14E46" minimumToolsVersion="Xcode 4.3">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16E195" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" syncable="YES"/>
<attribute name="hasVertebrae" attributeType="Boolean" syncable="YES"/>
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasVertebrae" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" elementID="numberOfFlippers" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="120"/>

View File

@@ -17,77 +17,76 @@ 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",
configuration: maleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_FB_Female.sqlite",
configuration: femaleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
dataStack.beginSynchronous { (transaction) -> Void in
transaction.deleteAll(From(UserAccount))
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Facebook"
account1.name = "John Smith HCD"
account1.friends = 42
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
account2.accountType = "Facebook"
account2.name = "Jane Doe HCD"
account2.friends = 314
transaction.commitAndWait()
}
_ = try? dataStack.perform(
synchronous: { (transaction) in
transaction.deleteAll(From<UserAccount>())
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Facebook"
account1.name = "John Smith HCD"
account1.friends = 42
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
account2.accountType = "Facebook"
account2.name = "Jane Doe HCD"
account2.friends = 314
}
)
return dataStack
}()
static let twitterStack: DataStack = {
let dataStack = DataStack(modelName: "StackSetupDemo")
let dataStack = DataStack(xcodeModelName: "StackSetupDemo")
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_TW_Male.sqlite",
configuration: maleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "AccountsDemo_TW_Female.sqlite",
configuration: femaleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
dataStack.beginSynchronous { (transaction) -> Void in
transaction.deleteAll(From(UserAccount))
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Twitter"
account1.name = "#johnsmith_hcd"
account1.friends = 7
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
account2.accountType = "Twitter"
account2.name = "#janedoe_hcd"
account2.friends = 100
transaction.commitAndWait()
}
_ = try? dataStack.perform(
synchronous: { (transaction) in
transaction.deleteAll(From<UserAccount>())
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Twitter"
account1.name = "#johnsmith_hcd"
account1.friends = 7
let account2 = transaction.create(Into<FemaleAccount>(femaleConfiguration))
account2.accountType = "Twitter"
account2.name = "#janedoe_hcd"
account2.friends = 100
}
)
return dataStack
}()
}
@@ -100,53 +99,53 @@ private struct Static {
class StackSetupDemoViewController: UITableViewController {
let accounts = [
Static.facebookStack.fetchAll(From(UserAccount)) ?? [],
Static.twitterStack.fetchAll(From(UserAccount)) ?? []
Static.facebookStack.fetchAll(From(UserAccount.self)) ?? [],
Static.twitterStack.fetchAll(From(UserAccount.self)) ?? []
]
// MARK: UIViewController
override func viewWillAppear(animated: Bool) {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)
self.updateDetailsWithAccount(self.accounts[indexPath.section][indexPath.row])
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
self.updateDetails(account: self.accounts[indexPath.section][indexPath.row])
}
override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Setup Demo",
message: "This demo shows how to initialize 2 DataStacks with 2 configurations each, for a total of 4 SQLite files, each with 1 instance of a \"UserAccount\" entity.",
preferredStyle: .Alert
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: UITableViewDataSource
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
override func numberOfSections(in tableView: UITableView) -> Int {
return self.accounts.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.accounts[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell")!
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")!
let account = self.accounts[indexPath.section][indexPath.row]
cell.textLabel?.text = account.name
@@ -158,13 +157,13 @@ class StackSetupDemoViewController: UITableViewController {
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let account = self.accounts[indexPath.section][indexPath.row]
self.updateDetailsWithAccount(account)
self.updateDetails(account: account)
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
@@ -188,7 +187,7 @@ class StackSetupDemoViewController: UITableViewController {
@IBOutlet private dynamic weak var nameLabel: UILabel?
@IBOutlet private dynamic weak var friendsLabel: UILabel?
private func updateDetailsWithAccount(account: UserAccount) {
private func updateDetails(account: UserAccount) {
self.accountTypeLabel?.text = account.accountType
self.nameLabel?.text = account.name

View File

@@ -11,7 +11,6 @@ import CoreLocation
import MapKit
import AddressBookUI
import CoreStore
import GCDKit
private struct Static {
@@ -22,21 +21,21 @@ private struct Static {
SQLiteStore(
fileName: "PlaceDemo.sqlite",
configuration: "TransactionsDemo",
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
var place = CoreStore.fetchOne(From(Place))
var place = CoreStore.fetchOne(From<Place>())
if place == nil {
CoreStore.beginSynchronous { (transaction) -> Void in
let place = transaction.create(Into(Place))
place.setInitialValues()
transaction.commitAndWait()
}
place = CoreStore.fetchOne(From(Place))
_ = try? CoreStore.perform(
synchronous: { (transaction) in
let place = transaction.create(Into<Place>())
place.setInitialValues()
}
)
place = CoreStore.fetchOne(From<Place>())
}
return CoreStore.monitorObject(place!)
@@ -71,33 +70,33 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
Static.placeController.addObserver(self)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .Refresh,
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.refreshButtonTapped(_:))
)
}
override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Transactions Demo",
message: "This demo shows how to use the 3 types of transactions to save updates: synchronous, asynchronous, and unsafe.\n\nTap and hold on the map to change the pin location.",
preferredStyle: .Alert
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func viewWillAppear(animated: Bool) {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let mapView = self.mapView, let place = Static.placeController.object {
mapView.addAnnotation(place)
mapView.setCenterCoordinate(place.coordinate, animated: false)
mapView.setCenter(place.coordinate, animated: false)
mapView.selectAnnotation(place, animated: false)
}
}
@@ -105,14 +104,14 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
// MARK: MKMapViewDelegate
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "MKAnnotationView"
var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView
var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.enabled = true
annotationView.isEnabled = true
annotationView.canShowCallout = true
annotationView.animatesDrop = true
}
@@ -127,28 +126,28 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
// MARK: ObjectObserver
func objectMonitor(monitor: ObjectMonitor<Place>, willUpdateObject object: Place) {
func objectMonitor(_ monitor: ObjectMonitor<Place>, willUpdateObject object: Place) {
// none
}
func objectMonitor(monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPath>) {
func objectMonitor(_ monitor: ObjectMonitor<Place>, didUpdateObject object: Place, changedPersistentKeys: Set<KeyPath>) {
if let mapView = self.mapView {
mapView.removeAnnotations(mapView.annotations ?? [])
mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotation(object)
mapView.setCenterCoordinate(object.coordinate, animated: true)
mapView.setCenter(object.coordinate, animated: true)
mapView.selectAnnotation(object, animated: true)
if changedPersistentKeys.contains("latitude") || changedPersistentKeys.contains("longitude") {
if changedPersistentKeys.contains(#keyPath(Place.latitude)) || changedPersistentKeys.contains(#keyPath(Place.longitude)) {
self.geocodePlace(object)
self.geocode(place: object)
}
}
}
func objectMonitor(monitor: ObjectMonitor<Place>, didDeleteObject object: Place) {
func objectMonitor(_ monitor: ObjectMonitor<Place>, didDeleteObject object: Place) {
// none
}
@@ -160,34 +159,39 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
@IBOutlet weak var mapView: MKMapView?
@IBAction dynamic func longPressGestureRecognized(sender: AnyObject?) {
@IBAction dynamic func longPressGestureRecognized(_ sender: AnyObject?) {
if let mapView = self.mapView, let gesture = sender as? UILongPressGestureRecognizer where gesture.state == .Began {
if let mapView = self.mapView,
let gesture = sender as? UILongPressGestureRecognizer,
gesture.state == .began {
let coordinate = mapView.convertPoint(
gesture.locationInView(mapView),
toCoordinateFromView: mapView
let coordinate = mapView.convert(
gesture.location(in: mapView),
toCoordinateFrom: mapView
)
CoreStore.beginAsynchronous { (transaction) -> Void in
CoreStore.perform(
asynchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object)
place?.coordinate = coordinate
},
completion: { _ in }
)
}
}
@IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
_ = try? CoreStore.perform(
synchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object)
place?.coordinate = coordinate
transaction.commit { (_) -> Void in }
place?.setInitialValues()
}
}
)
}
@IBAction dynamic func refreshButtonTapped(sender: AnyObject?) {
CoreStore.beginSynchronous { (transaction) -> Void in
let place = transaction.edit(Static.placeController.object)
place?.setInitialValues()
transaction.commitAndWait()
}
}
func geocodePlace(place: Place) {
func geocode(place: Place) {
let transaction = CoreStore.beginUnsafe()

View File

@@ -36,11 +36,12 @@ class BaseTestCase: XCTestCase {
// MARK: Internal
@nonobjc
func prepareStack<T>(configurations configurations: [String?] = [nil], @noescape _ closure: (dataStack: DataStack) -> T) -> T {
@discardableResult
func prepareStack<T>(configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T {
let stack = DataStack(
modelName: "Model",
bundle: NSBundle(forClass: self.dynamicType)
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
@@ -49,10 +50,10 @@ class BaseTestCase: XCTestCase {
try stack.addStorageAndWait(
SQLiteStore(
fileURL: SQLiteStore.defaultRootDirectory
.URLByAppendingPathComponent(NSUUID().UUIDString)
.URLByAppendingPathComponent("\(self.dynamicType)_\(($0 ?? "-null-")).sqlite"),
.appendingPathComponent(UUID().uuidString)
.appendingPathComponent("\(type(of: self))_\(($0 ?? "-null-")).sqlite"),
configuration: $0,
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
)
}
@@ -61,11 +62,11 @@ class BaseTestCase: XCTestCase {
XCTFail(error.coreStoreDumpString)
}
return closure(dataStack: stack)
return closure(stack)
}
@nonobjc
func expectLogger<T>(expectations: [TestLogger.Expectation], @noescape closure: () -> T) -> T {
func expectLogger<T>(_ expectations: [TestLogger.Expectation], closure: () -> T) -> T {
CoreStore.logger = TestLogger(self.prepareLoggerExpectations(expectations))
defer {
@@ -77,18 +78,18 @@ class BaseTestCase: XCTestCase {
}
@nonobjc
func expectLogger(expectations: [TestLogger.Expectation: XCTestExpectation]) {
func expectLogger(_ expectations: [TestLogger.Expectation: XCTestExpectation]) {
CoreStore.logger = TestLogger(expectations)
}
@nonobjc
func prepareLoggerExpectations(expectations: [TestLogger.Expectation]) -> [TestLogger.Expectation: XCTestExpectation] {
func prepareLoggerExpectations(_ expectations: [TestLogger.Expectation]) -> [TestLogger.Expectation: XCTestExpectation] {
var testExpectations: [TestLogger.Expectation: XCTestExpectation] = [:]
for expectation in expectations {
testExpectations[expectation] = self.expectationWithDescription("Logger Expectation: \(expectation)")
testExpectations[expectation] = self.expectation(description: "Logger Expectation: \(expectation)")
}
return testExpectations
}
@@ -96,13 +97,13 @@ class BaseTestCase: XCTestCase {
@nonobjc
func checkExpectationsImmediately() {
self.waitForExpectationsWithTimeout(0, handler: nil)
self.waitForExpectations(timeout: 0, handler: { _ in })
}
@nonobjc
func waitAndCheckExpectations() {
self.waitForExpectationsWithTimeout(10, handler: nil)
self.waitForExpectations(timeout: 10, handler: {_ in })
}
// MARK: XCTestCase
@@ -126,7 +127,7 @@ class BaseTestCase: XCTestCase {
private func deleteStores() {
_ = try? NSFileManager.defaultManager().removeItemAtURL(SQLiteStore.defaultRootDirectory)
_ = try? FileManager.default.removeItem(at: SQLiteStore.defaultRootDirectory)
}
}
@@ -137,11 +138,11 @@ class TestLogger: CoreStoreLogger {
enum Expectation {
case LogWarning
case LogFatal
case LogError
case AssertionFailure
case FatalError
case logWarning
case logFatal
case logError
case assertionFailure
case fatalError
}
init(_ expectations: [Expectation: XCTestExpectation]) {
@@ -152,33 +153,35 @@ class TestLogger: CoreStoreLogger {
// MARK: CoreStoreLogger
func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
var enableObjectConcurrencyDebugging: Bool = true
func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
switch level {
case .Warning: self.fulfill(.LogWarning)
case .Fatal: self.fulfill(.LogFatal)
case .warning: self.fulfill(.logWarning)
case .fatal: self.fulfill(.logFatal)
default: break
}
}
func log(error error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
self.fulfill(.LogError)
self.fulfill(.logError)
}
func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
if condition() {
return
}
self.fulfill(.AssertionFailure)
self.fulfill(.assertionFailure)
}
func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
self.fulfill(.FatalError)
self.fulfill(.fatalError)
}
@@ -186,7 +189,7 @@ class TestLogger: CoreStoreLogger {
private var expectations: [Expectation: XCTestExpectation]
private func fulfill(expectation: Expectation) {
private func fulfill(_ expectation: Expectation) {
if let instance = self.expectations[expectation] {

View File

@@ -17,60 +17,61 @@ import CoreStore
class BaseTestDataTestCase: BaseTestCase {
@nonobjc
let dateFormatter: NSDateFormatter = {
let dateFormatter: DateFormatter = cs_lazy {
let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.timeZone = NSTimeZone(name: "UTC")
formatter.calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
return formatter
}()
}
@nonobjc
func prepareTestDataForStack(stack: DataStack, configurations: [String?] = [nil]) {
func prepareTestDataForStack(_ stack: DataStack, configurations: [ModelConfiguration] = [nil]) {
stack.beginSynchronous { (transaction) in
for (configurationIndex, configuration) in configurations.enumerate() {
try! stack.perform(
synchronous: { (transaction) in
let configurationOrdinal = configurationIndex + 1
if configuration == nil || configuration == "Config1" {
for (configurationIndex, configuration) in configurations.enumerated() {
for idIndex in 1 ... 5 {
let configurationOrdinal = configurationIndex + 1
if configuration == nil || configuration == "Config1" {
let object = transaction.create(Into<TestEntity1>(configuration))
object.testEntityID = NSNumber(integer: (configurationOrdinal * 100) + idIndex)
object.testNumber = idIndex
object.testDate = self.dateFormatter.dateFromString("2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
object.testBoolean = (idIndex % 2) == 1
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
let string = "\(configuration ?? "nil"):TestEntity1:\(idIndex)"
object.testString = string
object.testData = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding)
for idIndex in 1 ... 5 {
let object = transaction.create(Into<TestEntity1>(configuration))
object.testEntityID = NSNumber(value: (configurationOrdinal * 100) + idIndex)
object.testNumber = NSNumber(value: idIndex)
object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
object.testBoolean = NSNumber(value: (idIndex % 2) == 1)
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
let string = "\(configuration ?? "nil"):TestEntity1:\(idIndex)"
object.testString = string
object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue)
}
}
}
if configuration == nil || configuration == "Config2" {
for idIndex in 1 ... 5 {
if configuration == nil || configuration == "Config2" {
let object = transaction.create(Into<TestEntity2>(configuration))
object.testEntityID = NSNumber(integer: (configurationOrdinal * 200) + idIndex)
object.testNumber = idIndex
object.testDate = self.dateFormatter.dateFromString("2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
object.testBoolean = (idIndex % 2) == 1
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
let string = "\(configuration ?? "nil"):TestEntity2:\(idIndex)"
object.testString = string
object.testData = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding)
for idIndex in 1 ... 5 {
let object = transaction.create(Into<TestEntity2>(configuration))
object.testEntityID = NSNumber(value: (configurationOrdinal * 200) + idIndex)
object.testNumber = NSNumber(value: idIndex)
object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z")
object.testBoolean = NSNumber(value: (idIndex % 2) == 1)
object.testDecimal = NSDecimalNumber(string: "\(idIndex)")
let string = "\(configuration ?? "nil"):TestEntity2:\(idIndex)"
object.testString = string
object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue)
}
}
}
}
transaction.commitAndWait()
}
)
}
}

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);
@@ -197,4 +197,61 @@
XCTAssertNil(sqliteError);
}
- (void)test_ThatTransactions_BridgeCorrectly {
[CSCoreStore
setDefaultStack:[[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]];
[CSCoreStore
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
{
CSUnsafeDataTransaction *transaction = [CSCoreStore beginUnsafe];
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
NSError *error;
BOOL result = [transaction commitAndWaitWithError:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
NSError *error;
BOOL result = [CSCoreStore
beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
NSError *error;
XCTAssertTrue([transaction commitAndWaitWithError:&error]);
XCTAssertNil(error);
[expectation fulfill];
}
error:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
[CSCoreStore beginAsynchronous:^(CSAsynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
[transaction
commitWithSuccess:^{
[expectation fulfill];
}
failure:^(CSError *error){
XCTFail();
}];
}];
}
[self waitForExpectationsWithTimeout:10 handler:nil];
}
@end

View File

@@ -0,0 +1,91 @@
//
// ConvenienceTests.swift
// CoreStore
//
// Copyright © 2016 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.
//
@testable
import CoreStore
// MARK: - ConvenienceTests
@available(OSX 10.12, *)
class ConvenienceTests: BaseTestCase {
@objc
dynamic func test_ThatDataStacks_CanCreateFetchedResultsControllers() {
self.prepareStack { (stack) in
let controller = stack.createFetchedResultsController(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testString)),
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
OrderBy(.ascending(#keyPath(TestEntity1.testString))),
Tweak { $0.fetchLimit = 10 }
)
XCTAssertEqual(controller.managedObjectContext, stack.mainContext)
XCTAssertEqual(controller.fetchRequest.entity?.managedObjectClassName, NSStringFromClass(TestEntity1.self))
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
XCTAssertEqual(
controller.fetchRequest.sortDescriptors!,
OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
)
XCTAssertEqual(
controller.fetchRequest.predicate,
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
)
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
}
}
@objc
dynamic func test_ThatUnsafeDataTransactions_CanCreateFetchedResultsControllers() {
self.prepareStack { (stack) in
_ = withExtendedLifetime(stack.beginUnsafe()) { (transaction: UnsafeDataTransaction) in
let controller = transaction.createFetchedResultsController(
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testString)),
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100),
OrderBy(.ascending(#keyPath(TestEntity1.testString))),
Tweak { $0.fetchLimit = 10 }
)
XCTAssertEqual(controller.managedObjectContext, transaction.context)
XCTAssertEqual(controller.fetchRequest.entity?.managedObjectClassName, NSStringFromClass(TestEntity1.self))
XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString))
XCTAssertEqual(
controller.fetchRequest.sortDescriptors!,
OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors
)
XCTAssertEqual(
controller.fetchRequest.predicate,
Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate
)
XCTAssertEqual(controller.fetchRequest.fetchLimit, 10)
}
}
}
}

View File

@@ -0,0 +1,259 @@
//
// DynamicModelTests.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import XCTest
@testable
import CoreStore
#if os(OSX)
typealias Color = NSColor
#else
typealias Color = UIColor
#endif
class Animal: CoreStoreObject {
let species = Value.Required<String>("species", default: "Swift")
let master = Relationship.ToOne<Person>("master")
let color = Transformable.Optional<Color>("color")
}
class Dog: Animal {
let nickname = Value.Optional<String>("nickname")
let age = Value.Required<Int>("age", default: 1)
let friends = Relationship.ToManyOrdered<Dog>("friends")
let friendedBy = Relationship.ToManyUnordered<Dog>("friendedBy", inverse: { $0.friends })
}
class Person: CoreStoreObject {
let title = Value.Required<String>(
"title",
default: "Mr.",
customSetter: { (`self`, setValue, originalNewValue) in
setValue(originalNewValue)
self.displayName .= nil
}
)
let name = Value.Required<String>(
"name",
customSetter: { (`self`, setValue, originalNewValue) in
setValue(originalNewValue)
self.displayName .= nil
}
)
let displayName = Value.Optional<String>(
"displayName",
isTransient: true,
customGetter: Person.cachedDisplayName(_:_:),
affectedByKeyPaths: Person.keyPathsAffectingDisplayName()
)
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
static func cachedDisplayName(_ instance: Person, _ getValue: () -> String?) -> String? {
if let cached = getValue() {
return cached
}
let primitiveValue = "\(instance.title.value) \(instance.name.value)"
instance.displayName .= primitiveValue
return primitiveValue
}
static func keyPathsAffectingDisplayName() -> Set<String> {
return [
self.keyPath({ $0.title }),
self.keyPath({ $0.name })
]
}
}
// MARK: - DynamicModelTests
class DynamicModelTests: BaseTestDataTestCase {
func testDynamicModels_CanBeDeclaredCorrectly() {
let dataStack = DataStack(
CoreStoreSchema(
modelVersion: "V1",
entities: [
Entity<Animal>("Animal"),
Entity<Dog>("Dog"),
Entity<Person>("Person")
],
versionLock: [
"Animal": [0x1b59d511019695cf, 0xdeb97e86c5eff179, 0x1cfd80745646cb3, 0x4ff99416175b5b9a],
"Dog": [0xe3f0afeb109b283a, 0x29998d292938eb61, 0x6aab788333cfc2a3, 0x492ff1d295910ea7],
"Person": [0x66d8bbfd8b21561f, 0xcecec69ecae3570f, 0xc4b73d71256214ef, 0x89b99bfe3e013e8b]
]
)
)
self.prepareStack(dataStack, configurations: [nil]) { (stack) in
let k1 = Animal.keyPath({ $0.species })
XCTAssertEqual(k1, "species")
let k2 = Dog.keyPath({ $0.species })
XCTAssertEqual(k2, "species")
let k3 = Dog.keyPath({ $0.nickname })
XCTAssertEqual(k3, "nickname")
let updateDone = self.expectation(description: "update-done")
let fetchDone = self.expectation(description: "fetch-done")
stack.perform(
asynchronous: { (transaction) in
let animal = transaction.create(Into<Animal>())
XCTAssertEqual(animal.species.value, "Swift")
XCTAssertTrue(type(of: animal.species.value) == String.self)
animal.species .= "Sparrow"
XCTAssertEqual(animal.species.value, "Sparrow")
animal.color .= .yellow
XCTAssertEqual(animal.color.value, Color.yellow)
let dog = transaction.create(Into<Dog>())
XCTAssertEqual(dog.species.value, "Swift")
XCTAssertEqual(dog.nickname.value, nil)
XCTAssertEqual(dog.age.value, 1)
dog.species .= "Dog"
XCTAssertEqual(dog.species.value, "Dog")
dog.nickname .= "Spot"
XCTAssertEqual(dog.nickname.value, "Spot")
let person = transaction.create(Into<Person>())
XCTAssertTrue(person.pets.value.isEmpty)
XCTAssertEqual(
object_getClass(person.rawObject!).keyPathsForValuesAffectingValue(forKey: "displayName"),
["title", "name"]
)
person.name .= "Joe"
XCTAssertEqual(person.rawObject!.value(forKey: "name") as! String?, "Joe")
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "Mr. Joe")
person.rawObject!.setValue("AAAA", forKey: "displayName")
XCTAssertEqual(person.rawObject!.value(forKey: "displayName") as! String?, "AAAA")
person.name .= "John"
XCTAssertEqual(person.name.value, "John")
XCTAssertEqual(person.displayName.value, "Mr. John") // Custom getter
person.title .= "Sir"
XCTAssertEqual(person.displayName.value, "Sir John")
person.pets.value.insert(dog)
XCTAssertEqual(person.pets.count, 1)
XCTAssertEqual(person.pets.value.first, dog)
XCTAssertEqual(person.pets.value.first?.master.value, person)
XCTAssertEqual(dog.master.value, person)
XCTAssertEqual(dog.master.value?.pets.value.first, dog)
},
success: {
updateDone.fulfill()
},
failure: { _ in
XCTFail()
}
)
stack.perform(
asynchronous: { (transaction) in
let p1 = Animal.where({ $0.species == "Sparrow" })
XCTAssertEqual(p1.predicate, NSPredicate(format: "%K == %@", "species", "Sparrow"))
let bird = transaction.fetchOne(From<Animal>(), p1)
XCTAssertNotNil(bird)
XCTAssertEqual(bird!.species.value, "Sparrow")
let p2 = Dog.where({ $0.nickname == "Spot" })
XCTAssertEqual(p2.predicate, NSPredicate(format: "%K == %@", "nickname", "Spot"))
let dog = transaction.fetchOne(From<Dog>(), p2)
XCTAssertNotNil(dog)
XCTAssertEqual(dog!.nickname.value, "Spot")
XCTAssertEqual(dog!.species.value, "Dog")
let person = transaction.fetchOne(From<Person>())
XCTAssertNotNil(person)
XCTAssertEqual(person!.pets.value.first, dog)
let p3 = Dog.where({ $0.age == 10 })
XCTAssertEqual(p3.predicate, NSPredicate(format: "%K == %d", "age", 10))
},
success: {
fetchDone.fulfill()
},
failure: { _ in
XCTFail()
}
)
self.waitAndCheckExpectations()
}
}
@nonobjc
func prepareStack(_ dataStack: DataStack, configurations: [ModelConfiguration] = [nil], _ closure: (_ dataStack: DataStack) -> Void) {
do {
try configurations.forEach { (configuration) in
try dataStack.addStorageAndWait(
SQLiteStore(
fileURL: SQLiteStore.defaultRootDirectory
.appendingPathComponent(UUID().uuidString)
.appendingPathComponent("\(type(of: self))_\((configuration ?? "-null-")).sqlite"),
configuration: configuration,
localStorageOptions: .recreateStoreOnModelMismatch
)
)
}
}
catch let error as NSError {
XCTFail(error.coreStoreDumpString)
}
closure(dataStack)
}
}

View File

@@ -36,33 +36,33 @@ final class ErrorTests: XCTestCase {
@objc
dynamic func test_ThatUnknownErrors_BridgeCorrectly() {
let error = CoreStoreError.Unknown
let error = CoreStoreError.unknown
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.UnknownError.rawValue)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.unknownError.rawValue)
let userInfo: NSDictionary = [:]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.UnknownError.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.UnknownError.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
}
@objc
dynamic func test_ThatDifferentStorageExistsAtURLErrors_BridgeCorrectly() {
let dummyURL = NSURL(string: "file:///test1/test2.sqlite")!
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
let error = CoreStoreError.DifferentStorageExistsAtURL(existingPersistentStoreURL: dummyURL)
let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: dummyURL)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
let userInfo: NSDictionary = [
"existingPersistentStoreURL": dummyURL
@@ -70,54 +70,59 @@ final class ErrorTests: XCTestCase {
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
}
@objc
dynamic func test_ThatMappingModelNotFoundErrors_BridgeCorrectly() {
let dummyURL = NSURL(string: "file:///test1/test2.sqlite")!
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
let model = NSManagedObjectModel.fromBundle(NSBundle(forClass: self.dynamicType), modelName: "Model")
let schemaHistory = SchemaHistory(
XcodeDataModelSchema.from(
modelName: "Model",
bundle: Bundle(for: type(of: self))
)
)
let version = "1.0.0"
let error = CoreStoreError.MappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version)
let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: schemaHistory.rawModel, targetModelVersion: version)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.MappingModelNotFound.rawValue)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
let userInfo: NSDictionary = [
"localStoreURL": dummyURL,
"targetModel": model,
"targetModel": schemaHistory.rawModel,
"targetModelVersion": version
]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.MappingModelNotFound.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.MappingModelNotFound.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
}
@objc
dynamic func test_ThatProgressiveMigrationRequiredErrors_BridgeCorrectly() {
let dummyURL = NSURL(string: "file:///test1/test2.sqlite")!
let dummyURL = URL(string: "file:///test1/test2.sqlite")!
let error = CoreStoreError.ProgressiveMigrationRequired(localStoreURL: dummyURL)
let error = CoreStoreError.progressiveMigrationRequired(localStoreURL: dummyURL)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
let userInfo: NSDictionary = [
"localStoreURL": dummyURL
@@ -125,14 +130,14 @@ final class ErrorTests: XCTestCase {
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
}
@objc
@@ -144,12 +149,12 @@ final class ErrorTests: XCTestCase {
userInfo: [
"key1": "value1",
"key2": 2,
"key3": NSDate()
"key3": Date()
]
)
let error = CoreStoreError.InternalError(NSError: internalError)
let error = CoreStoreError(internalError)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.InternalError.rawValue)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.internalError.rawValue)
let userInfo: NSDictionary = [
"NSError": internalError
@@ -157,13 +162,13 @@ final class ErrorTests: XCTestCase {
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.InternalError.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.InternalError.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,7 @@ final class FromTests: BaseTestCase {
do {
let from = From()
let from = From<NSManagedObject>()
XCTAssert(from.entityClass === NSManagedObject.self)
XCTAssertNil(from.configurations)
}
@@ -74,33 +74,33 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"])
}
do {
let from = From<TestEntity1>("Config1")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
}
@@ -115,102 +115,102 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"])
}
do {
let from = From<TestEntity1>("Config1")
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"])
}
do {
let from = From<TestEntity1>("Config2")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>()
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>("Config1")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>("Config2")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
}
@@ -225,99 +225,99 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(Set(affectedConfigurations), ["PF_DEFAULT_CONFIGURATION_NAME", "Config1"] as Set)
}
do {
let from = From<TestEntity1>("Config1")
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"])
}
do {
let from = From<TestEntity1>("Config2")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>()
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"])
}
do {
let from = From<TestEntity2>("Config1")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>("Config2")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
}
@@ -332,96 +332,96 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>()
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"])
}
do {
let from = From<TestEntity1>("Config1")
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"])
}
do {
let from = From<TestEntity1>("Config2")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>()
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config2"])
}
do {
let from = From<TestEntity2>("Config1")
let request = NSFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) {
let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext)
}
XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty)
}
do {
let from = From<TestEntity2>("Config2")
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores)
XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName }
let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config2"])
}
}

View File

@@ -66,10 +66,10 @@ final class GroupByTests: BaseTestCase {
self.prepareStack { (dataStack) in
let groupBy = GroupBy("testString")
let groupBy = GroupBy(#keyPath(TestEntity1.testString))
let request = NSFetchRequest()
_ = From(TestEntity1).applyToFetchRequest(request, context: dataStack.mainContext)
let request = CoreStoreFetchRequest()
_ = From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext)
groupBy.applyToFetchRequest(request)
XCTAssertNotNil(request.propertiesToGroupBy)

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,7 @@ final class IntoTests: XCTestCase {
@objc
dynamic func test_ThatIntoClauseConstants_AreCorrect() {
XCTAssertEqual(Into<NSManagedObject>.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
XCTAssertEqual(DataStack.defaultConfigurationName, "PF_DEFAULT_CONFIGURATION_NAME")
}
@objc
@@ -44,7 +44,7 @@ final class IntoTests: XCTestCase {
do {
let into = Into()
let into = Into<NSManagedObject>()
XCTAssert(into.entityClass === NSManagedObject.self)
XCTAssertNil(into.configuration)
XCTAssertTrue(into.inferStoreIfPossible)
@@ -58,14 +58,7 @@ final class IntoTests: XCTestCase {
}
do {
let into = Into(TestEntity1)
XCTAssert(into.entityClass === TestEntity1.self)
XCTAssertNil(into.configuration)
XCTAssertTrue(into.inferStoreIfPossible)
}
do {
let into = Into(TestEntity1.self as AnyClass)
let into = Into(TestEntity1.self)
XCTAssert(into.entityClass === TestEntity1.self)
XCTAssertNil(into.configuration)
XCTAssertTrue(into.inferStoreIfPossible)
@@ -84,13 +77,6 @@ final class IntoTests: XCTestCase {
XCTAssertEqual(into.configuration, "Config1")
XCTAssertFalse(into.inferStoreIfPossible)
}
do {
let into = Into(TestEntity1.self as AnyClass, "Config1")
XCTAssert(into.entityClass === TestEntity1.self)
XCTAssertEqual(into.configuration, "Config1")
XCTAssertFalse(into.inferStoreIfPossible)
}
}
@objc
@@ -98,43 +84,30 @@ final class IntoTests: XCTestCase {
do {
let into = Into()
XCTAssertEqual(into, Into())
let into = Into<NSManagedObject>()
XCTAssertEqual(into, Into<NSManagedObject>())
XCTAssertEqual(into, Into(NSManagedObject.self as AnyClass))
XCTAssertFalse(into == Into<TestEntity1>())
XCTAssertEqual(into, Into(NSManagedObject.self))
XCTAssertNotEqual(into, Into<NSManagedObject>(TestEntity1.self))
XCTAssertNotEqual(into, Into<NSManagedObject>("Config1"))
}
do {
let into = Into<TestEntity1>()
XCTAssertEqual(into, Into(TestEntity1))
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
XCTAssertFalse(into == Into<TestEntity2>())
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
}
do {
let into = Into(TestEntity1)
XCTAssertEqual(into, Into<TestEntity1>())
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass))
XCTAssertFalse(into == Into<TestEntity2>())
XCTAssertEqual(into, Into(TestEntity1.self))
XCTAssertNotEqual(into, Into<TestEntity1>("Config1"))
}
do {
let into = Into(TestEntity1.self as AnyClass)
let into = Into(TestEntity1.self)
XCTAssert(into == Into<TestEntity1>())
XCTAssertEqual(into, Into(TestEntity1))
XCTAssertFalse(into == Into<TestEntity2>())
XCTAssertEqual(into, Into(TestEntity1.self))
XCTAssertFalse(into == Into<TestEntity1>("Config1"))
}
do {
let into = Into<TestEntity1>("Config1")
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
XCTAssertEqual(into, Into(TestEntity1.self as AnyClass, "Config1"))
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
}
do {
@@ -142,16 +115,14 @@ final class IntoTests: XCTestCase {
let into = Into(TestEntity1.self, "Config1")
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
}
do {
let into = Into(TestEntity1.self as AnyClass, "Config1")
XCTAssert(into == Into<TestEntity1>("Config1"))
let into = Into(TestEntity1.self, "Config1")
XCTAssertEqual(into, Into<TestEntity1>("Config1"))
XCTAssertEqual(into, Into(TestEntity1.self, "Config1"))
XCTAssertFalse(into == Into<TestEntity2>("Config1"))
XCTAssertFalse(into == Into<TestEntity1>("Config2"))
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
}
}
@@ -160,45 +131,9 @@ final class IntoTests: XCTestCase {
do {
let into = Into()
let into = Into<NSManagedObject>()
let objcInto = into.bridgeToObjectiveC
XCTAssertEqual(into, objcInto.bridgeToSwift)
}
do {
let into = Into<TestEntity1>()
let objcInto = into.bridgeToObjectiveC
XCTAssertTrue(into == objcInto.bridgeToSwift)
}
do {
let into = Into(TestEntity1.self as AnyClass)
let objcInto = into.bridgeToObjectiveC
XCTAssertEqual(into, objcInto.bridgeToSwift)
}
do {
let into = Into(TestEntity1.self as AnyClass)
let objcInto = into.bridgeToObjectiveC
XCTAssertEqual(into, objcInto.bridgeToSwift)
}
do {
let into = Into<TestEntity1>("Config1")
let objcInto = into.bridgeToObjectiveC
XCTAssertTrue(into == objcInto.bridgeToSwift)
}
do {
let into = Into(TestEntity1.self, "Config1")
let objcInto = into.bridgeToObjectiveC
XCTAssertTrue(into == objcInto.bridgeToSwift)
}
do {
let into = Into(TestEntity1.self as AnyClass, "Config1")
let objcInto = into.bridgeToObjectiveC
XCTAssertTrue(into == objcInto.bridgeToSwift)
}
}
}

View File

@@ -29,10 +29,9 @@ import XCTest
import CoreStore
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - ListObserverTests
@available(OSX 10.12, *)
class ListObserverTests: BaseTestDataTestCase {
@objc
@@ -42,9 +41,9 @@ class ListObserverTests: BaseTestDataTestCase {
let observer = TestListObserver()
let monitor = stack.monitorSectionedList(
From(TestEntity1),
SectionBy("testBoolean"),
OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID"))
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
@@ -54,13 +53,13 @@ class ListObserverTests: BaseTestDataTestCase {
var events = 0
let willChangeExpectation = self.expectationForNotification(
"listMonitorWillChange:",
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -68,14 +67,14 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 0
}
)
let didInsertSectionExpectation = self.expectationForNotification(
"listMonitor:didInsertSection:toSectionIndex:",
let didInsertSectionExpectation = self.expectation(
forNotification: "listMonitor:didInsertSection:toSectionIndex:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 1)
XCTAssertEqual(
(note.userInfo ?? [:]),
((note.userInfo as NSDictionary?) ?? [:]),
[
"sectionInfo": monitor.sectionInfoAtIndex(0),
"sectionIndex": 0
@@ -88,8 +87,8 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 1
}
)
let didInsertObjectExpectation = self.expectationForNotification(
"listMonitor:didInsertObject:toIndexPath:",
let didInsertObjectExpectation = self.expectation(
forNotification: "listMonitor:didInsertObject:toIndexPath:",
object: observer,
handler: { (note) -> Bool in
@@ -98,21 +97,21 @@ class ListObserverTests: BaseTestDataTestCase {
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? NSIndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.row, 0)
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testBoolean, NSNumber(bool: true))
XCTAssertEqual(object?.testNumber, NSNumber(integer: 1))
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 1))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:1")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!)
XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!)
defer {
events += 1
@@ -120,12 +119,12 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 2
}
)
let didChangeExpectation = self.expectationForNotification(
"listMonitorDidChange:",
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -133,30 +132,30 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 3
}
)
let saveExpectation = self.expectationWithDescription("save")
stack.beginAsynchronous { (transaction) in
let object = transaction.create(Into(TestEntity1))
object.testBoolean = NSNumber(bool: true)
object.testNumber = NSNumber(integer: 1)
object.testDecimal = NSDecimalNumber(string: "1")
object.testString = "nil:TestEntity1:1"
object.testData = ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!
object.testDate = self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!
transaction.commit { (result) in
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
switch result {
case .Success(let hasChanges):
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
case .Failure:
XCTFail()
}
let object = transaction.create(Into<TestEntity1>())
object.testBoolean = NSNumber(value: true)
object.testNumber = NSNumber(value: 1)
object.testDecimal = NSDecimalNumber(string: "1")
object.testString = "nil:TestEntity1:1"
object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
}
)
self.waitAndCheckExpectations()
}
}
@@ -170,9 +169,9 @@ class ListObserverTests: BaseTestDataTestCase {
let observer = TestListObserver()
let monitor = stack.monitorSectionedList(
From(TestEntity1),
SectionBy("testBoolean"),
OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID"))
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
@@ -185,13 +184,13 @@ class ListObserverTests: BaseTestDataTestCase {
var events = 0
let willChangeExpectation = self.expectationForNotification(
"listMonitorWillChange:",
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -201,8 +200,8 @@ class ListObserverTests: BaseTestDataTestCase {
)
for _ in 1 ... 2 {
let didUpdateObjectExpectation = self.expectationForNotification(
"listMonitor:didUpdateObject:atIndexPath:",
let didUpdateObjectExpectation = self.expectation(
forNotification: "listMonitor:didUpdateObject:atIndexPath:",
object: observer,
handler: { (note) -> Bool in
@@ -211,7 +210,7 @@ class ListObserverTests: BaseTestDataTestCase {
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
@@ -220,27 +219,27 @@ class ListObserverTests: BaseTestDataTestCase {
switch object?.testEntityID {
case NSNumber(integer: 101)?:
XCTAssertEqual(indexPath?.section, 1)
XCTAssertEqual(indexPath?.row, 0)
case NSNumber(value: 101)?:
XCTAssertEqual(indexPath?.index(atPosition: 0), 1)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
XCTAssertEqual(object?.testBoolean, NSNumber(bool: true))
XCTAssertEqual(object?.testNumber, NSNumber(integer: 11))
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).dataUsingEncoding(NSUTF8StringEncoding)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-11T00:00:00Z")!)
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(integer: 102)?:
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.row, 0)
case NSNumber(value: 102)?:
XCTAssertEqual(indexPath?.index(atPosition: 0), 0)
XCTAssertEqual(indexPath?.index(atPosition: 1), 0)
XCTAssertEqual(object?.testBoolean, NSNumber(bool: false))
XCTAssertEqual(object?.testNumber, NSNumber(integer: 22))
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).dataUsingEncoding(NSUTF8StringEncoding)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-22T00:00:00Z")!)
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()
@@ -253,13 +252,13 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
}
let didChangeExpectation = self.expectationForNotification(
"listMonitorDidChange:",
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 3)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -267,50 +266,50 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 3
}
)
let saveExpectation = self.expectationWithDescription("save")
stack.beginAsynchronous { (transaction) in
if let object = transaction.fetchOne(
From(TestEntity1),
Where("testEntityID", isEqualTo: 101)) {
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
object.testNumber = NSNumber(integer: 11)
object.testDecimal = NSDecimalNumber(string: "11")
object.testString = "nil:TestEntity1:11"
object.testData = ("nil:TestEntity1:11" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!
object.testDate = self.dateFormatter.dateFromString("2000-01-11T00:00:00Z")!
}
else {
XCTFail()
}
if let object = transaction.fetchOne(
From(TestEntity1),
Where("testEntityID", isEqualTo: 102)) {
object.testNumber = NSNumber(integer: 22)
object.testDecimal = NSDecimalNumber(string: "22")
object.testString = "nil:TestEntity1:22"
object.testData = ("nil:TestEntity1:22" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!
object.testDate = self.dateFormatter.dateFromString("2000-01-22T00:00:00Z")!
}
else {
XCTFail()
}
transaction.commit { (result) in
switch result {
if let object = transaction.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) {
case .Success(let hasChanges):
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
object.testNumber = NSNumber(value: 11)
object.testDecimal = NSDecimalNumber(string: "11")
object.testString = "nil:TestEntity1:11"
object.testData = ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!
}
else {
case .Failure:
XCTFail()
}
if let object = transaction.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
object.testNumber = NSNumber(value: 22)
object.testDecimal = NSDecimalNumber(string: "22")
object.testString = "nil:TestEntity1:22"
object.testData = ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!
}
else {
XCTFail()
}
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
}
)
self.waitAndCheckExpectations()
}
}
@@ -324,21 +323,21 @@ class ListObserverTests: BaseTestDataTestCase {
let observer = TestListObserver()
let monitor = stack.monitorSectionedList(
From(TestEntity1),
SectionBy("testBoolean"),
OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID"))
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
var events = 0
let willChangeExpectation = self.expectationForNotification(
"listMonitorWillChange:",
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -346,8 +345,8 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 0
}
)
let didMoveObjectExpectation = self.expectationForNotification(
"listMonitor:didMoveObject:fromIndexPath:toIndexPath:",
let didMoveObjectExpectation = self.expectation(
forNotification: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:",
object: observer,
handler: { (note) -> Bool in
@@ -356,21 +355,21 @@ class ListObserverTests: BaseTestDataTestCase {
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["fromIndexPath", "toIndexPath", "object"]
)
let fromIndexPath = userInfo?["fromIndexPath"] as? NSIndexPath
XCTAssertEqual(fromIndexPath?.section, 0)
XCTAssertEqual(fromIndexPath?.row, 0)
XCTAssertEqual(fromIndexPath?.index(atPosition: 0), 0)
XCTAssertEqual(fromIndexPath?.index(atPosition: 1), 0)
let toIndexPath = userInfo?["toIndexPath"] as? NSIndexPath
XCTAssertEqual(toIndexPath?.section, 1)
XCTAssertEqual(toIndexPath?.row, 1)
XCTAssertEqual(toIndexPath?.index(atPosition: 0), 1)
XCTAssertEqual(toIndexPath?.index(atPosition: 1), 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 102))
XCTAssertEqual(object?.testBoolean, NSNumber(bool: true))
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
defer {
@@ -379,13 +378,13 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 1
}
)
let didChangeExpectation = self.expectationForNotification(
"listMonitorDidChange:",
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 2)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -393,32 +392,32 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 2
}
)
let saveExpectation = self.expectationWithDescription("save")
stack.beginAsynchronous { (transaction) in
if let object = transaction.fetchOne(
From(TestEntity1),
Where("testEntityID", isEqualTo: 102)) {
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
object.testBoolean = NSNumber(bool: true)
}
else {
if let object = transaction.fetchOne(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) {
object.testBoolean = NSNumber(value: true)
}
else {
XCTFail()
}
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
transaction.commit { (result) in
switch result {
case .Success(let hasChanges):
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
case .Failure:
XCTFail()
}
}
}
)
self.waitAndCheckExpectations()
}
}
@@ -432,21 +431,21 @@ class ListObserverTests: BaseTestDataTestCase {
let observer = TestListObserver()
let monitor = stack.monitorSectionedList(
From(TestEntity1),
SectionBy("testBoolean"),
OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID"))
From<TestEntity1>(),
SectionBy(#keyPath(TestEntity1.testBoolean)),
OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID)))
)
monitor.addObserver(observer)
var events = 0
let willChangeExpectation = self.expectationForNotification(
"listMonitorWillChange:",
let willChangeExpectation = self.expectation(
forNotification: "listMonitorWillChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -456,8 +455,8 @@ class ListObserverTests: BaseTestDataTestCase {
)
for _ in 1 ... 2 {
let didUpdateObjectExpectation = self.expectationForNotification(
"listMonitor:didDeleteObject:fromIndexPath:",
let didUpdateObjectExpectation = self.expectation(
forNotification: "listMonitor:didDeleteObject:fromIndexPath:",
object: observer,
handler: { (note) -> Bool in
@@ -466,17 +465,17 @@ class ListObserverTests: BaseTestDataTestCase {
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? NSIndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssert(indexPath?.row == 0 || indexPath?.row == 1)
XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.deleted, true)
XCTAssertEqual(object?.isDeleted, true)
defer {
@@ -486,8 +485,8 @@ class ListObserverTests: BaseTestDataTestCase {
}
)
}
let didDeleteSectionExpectation = self.expectationForNotification(
"listMonitor:didDeleteSection:fromSectionIndex:",
let didDeleteSectionExpectation = self.expectation(
forNotification: "listMonitor:didDeleteSection:fromSectionIndex:",
object: observer,
handler: { (note) -> Bool in
@@ -496,16 +495,16 @@ class ListObserverTests: BaseTestDataTestCase {
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["sectionInfo", "sectionIndex"]
)
let sectionInfo = userInfo?["sectionInfo"]
let sectionInfo = userInfo?["sectionInfo"] as? NSFetchedResultsSectionInfo
XCTAssertNotNil(sectionInfo)
XCTAssertEqual(sectionInfo?.name, "0")
let sectionIndex = userInfo?["sectionIndex"]
XCTAssertEqual(sectionIndex as? NSNumber, NSNumber(integer: 0))
XCTAssertEqual(sectionIndex as? NSNumber, NSNumber(value: 0))
defer {
@@ -514,13 +513,13 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 3
}
)
let didChangeExpectation = self.expectationForNotification(
"listMonitorDidChange:",
let didChangeExpectation = self.expectation(
forNotification: "listMonitorDidChange:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 4)
XCTAssertEqual((note.userInfo ?? [:]), NSDictionary())
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
@@ -528,26 +527,26 @@ class ListObserverTests: BaseTestDataTestCase {
return events == 4
}
)
let saveExpectation = self.expectationWithDescription("save")
stack.beginAsynchronous { (transaction) in
transaction.deleteAll(
From(TestEntity1),
Where("testBoolean", isEqualTo: false)
)
transaction.commit { (result) in
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
switch result {
case .Success(let hasChanges):
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
case .Failure:
XCTFail()
}
transaction.deleteAll(
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false)
)
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
}
}
)
self.waitAndCheckExpectations()
}
}
@@ -556,43 +555,44 @@ class ListObserverTests: BaseTestDataTestCase {
// MARK: TestListObserver
@available(OSX 10.12, *)
class TestListObserver: ListSectionObserver {
// MARK: ListObserver
typealias ListEntityType = TestEntity1
func listMonitorWillChange(monitor: ListMonitor<TestEntity1>) {
func listMonitorWillChange(_ monitor: ListMonitor<TestEntity1>) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitorWillChange:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitorWillChange:"),
object: self,
userInfo: [:]
)
}
func listMonitorDidChange(monitor: ListMonitor<TestEntity1>) {
func listMonitorDidChange(_ monitor: ListMonitor<TestEntity1>) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitorDidChange:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitorDidChange:"),
object: self,
userInfo: [:]
)
}
func listMonitorWillRefetch(monitor: ListMonitor<TestEntity1>) {
func listMonitorWillRefetch(_ monitor: ListMonitor<TestEntity1>) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitorWillRefetch:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitorWillRefetch:"),
object: self,
userInfo: [:]
)
}
func listMonitorDidRefetch(monitor: ListMonitor<TestEntity1>) {
func listMonitorDidRefetch(_ monitor: ListMonitor<TestEntity1>) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitorDidRefetch:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitorDidRefetch:"),
object: self,
userInfo: [:]
)
@@ -601,10 +601,10 @@ class TestListObserver: ListSectionObserver {
// MARK: ListObjectObserver
func listMonitor(monitor: ListMonitor<TestEntity1>, didInsertObject object: TestEntity1, toIndexPath indexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<TestEntity1>, didInsertObject object: TestEntity1, toIndexPath indexPath: IndexPath) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitor:didInsertObject:toIndexPath:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitor:didInsertObject:toIndexPath:"),
object: self,
userInfo: [
"object": object,
@@ -613,10 +613,10 @@ class TestListObserver: ListSectionObserver {
)
}
func listMonitor(monitor: ListMonitor<TestEntity1>, didDeleteObject object: TestEntity1, fromIndexPath indexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<TestEntity1>, didDeleteObject object: TestEntity1, fromIndexPath indexPath: IndexPath) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitor:didDeleteObject:fromIndexPath:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitor:didDeleteObject:fromIndexPath:"),
object: self,
userInfo: [
"object": object,
@@ -625,10 +625,10 @@ class TestListObserver: ListSectionObserver {
)
}
func listMonitor(monitor: ListMonitor<TestEntity1>, didUpdateObject object: TestEntity1, atIndexPath indexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<TestEntity1>, didUpdateObject object: TestEntity1, atIndexPath indexPath: IndexPath) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitor:didUpdateObject:atIndexPath:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitor:didUpdateObject:atIndexPath:"),
object: self,
userInfo: [
"object": object,
@@ -638,10 +638,10 @@ class TestListObserver: ListSectionObserver {
}
func listMonitor(monitor: ListMonitor<TestEntity1>, didMoveObject object: TestEntity1, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
func listMonitor(_ monitor: ListMonitor<TestEntity1>, didMoveObject object: TestEntity1, fromIndexPath: IndexPath, toIndexPath: IndexPath) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitor:didMoveObject:fromIndexPath:toIndexPath:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:"),
object: self,
userInfo: [
"object": object,
@@ -654,10 +654,10 @@ class TestListObserver: ListSectionObserver {
// MARK: ListSectionObserver
func listMonitor(monitor: ListMonitor<TestEntity1>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) {
func listMonitor(_ monitor: ListMonitor<TestEntity1>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitor:didInsertSection:toSectionIndex:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitor:didInsertSection:toSectionIndex:"),
object: self,
userInfo: [
"sectionInfo": sectionInfo,
@@ -666,10 +666,10 @@ class TestListObserver: ListSectionObserver {
)
}
func listMonitor(monitor: ListMonitor<TestEntity1>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
func listMonitor(_ monitor: ListMonitor<TestEntity1>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
NSNotificationCenter.defaultCenter().postNotificationName(
"listMonitor:didDeleteSection:fromSectionIndex:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "listMonitor:didDeleteSection:fromSectionIndex:"),
object: self,
userInfo: [
"sectionInfo": sectionInfo,
@@ -678,5 +678,3 @@ class TestListObserver: ListSectionObserver {
)
}
}
#endif

View File

@@ -37,8 +37,8 @@ final class MigrationChainTests: XCTestCase {
dynamic func test_ThatNilMigrationChains_HaveNoVersions() {
let chain: MigrationChain = nil
XCTAssertTrue(chain.valid)
XCTAssertTrue(chain.empty)
XCTAssertTrue(chain.isValid)
XCTAssertTrue(chain.isEmpty)
XCTAssertFalse(chain.contains("version1"))
XCTAssertNil(chain.nextVersionFrom("version1"))
@@ -48,8 +48,8 @@ final class MigrationChainTests: XCTestCase {
dynamic func test_ThatStringMigrationChains_HaveOneVersion() {
let chain: MigrationChain = "version1"
XCTAssertTrue(chain.valid)
XCTAssertTrue(chain.empty)
XCTAssertTrue(chain.isValid)
XCTAssertTrue(chain.isEmpty)
XCTAssertTrue(chain.contains("version1"))
XCTAssertFalse(chain.contains("version2"))
@@ -62,8 +62,8 @@ final class MigrationChainTests: XCTestCase {
dynamic func test_ThatArrayMigrationChains_HaveLinearVersions() {
let chain: MigrationChain = ["version1", "version2", "version3", "version4"]
XCTAssertTrue(chain.valid)
XCTAssertFalse(chain.empty)
XCTAssertTrue(chain.isValid)
XCTAssertFalse(chain.isEmpty)
XCTAssertTrue(chain.contains("version1"))
XCTAssertTrue(chain.contains("version2"))
@@ -86,8 +86,8 @@ final class MigrationChainTests: XCTestCase {
"version2": "version3",
"version3": "version4"
]
XCTAssertTrue(chain.valid)
XCTAssertFalse(chain.empty)
XCTAssertTrue(chain.isValid)
XCTAssertFalse(chain.isEmpty)
XCTAssertTrue(chain.contains("version1"))
XCTAssertTrue(chain.contains("version2"))

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10174" systemVersion="15F34" minimumToolsVersion="Xcode 4.3">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11759" systemVersion="16C67" minimumToolsVersion="Xcode 4.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="TestEntity1AAA" representedClassName="CoreStoreTests.TestEntity1" syncable="YES">
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
<attribute name="testNumber" optional="YES" attributeType="Integer 32" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
</entity>
<entity name="TestEntity2" representedClassName="CoreStoreTests.TestEntity2" syncable="YES">
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
<attribute name="testBoolean" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
<attribute name="testDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
<attribute name="testNumber" optional="YES" attributeType="Integer 32" usesScalarValueType="NO" syncable="YES"/>
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
</entity>
<configuration name="Config1">

View File

@@ -29,10 +29,9 @@ import XCTest
import CoreStore
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - ObjectObserverTests
@available(OSX 10.12, *)
class ObjectObserverTests: BaseTestDataTestCase {
@objc
@@ -43,8 +42,8 @@ class ObjectObserverTests: BaseTestDataTestCase {
self.prepareTestDataForStack(stack)
guard let object = stack.fetchOne(
From(TestEntity1),
Where("testEntityID", isEqualTo: 101)) else {
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
XCTFail()
return
@@ -58,14 +57,14 @@ class ObjectObserverTests: BaseTestDataTestCase {
var events = 0
let willUpdateExpectation = self.expectationForNotification(
"objectMonitor:willUpdateObject:",
let willUpdateExpectation = self.expectation(
forNotification: "objectMonitor:willUpdateObject:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual(
(note.userInfo ?? [:]),
((note.userInfo as NSDictionary?) ?? [:]),
["object": object] as NSDictionary
)
defer {
@@ -75,26 +74,26 @@ class ObjectObserverTests: BaseTestDataTestCase {
return events == 0
}
)
let didUpdateExpectation = self.expectationForNotification(
"objectMonitor:didUpdateObject:changedPersistentKeys:",
let didUpdateExpectation = self.expectation(
forNotification: "objectMonitor:didUpdateObject:changedPersistentKeys:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 1)
XCTAssertEqual(
(note.userInfo ?? [:]),
((note.userInfo as NSDictionary?) ?? [:]),
[
"object": object,
"changedPersistentKeys": Set(
[
"testNumber",
"testString"
#keyPath(TestEntity1.testNumber),
#keyPath(TestEntity1.testString)
]
)
] as NSDictionary
)
let object = note.userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testNumber, NSNumber(integer: 10))
XCTAssertEqual(object?.testNumber, NSNumber(value: 10))
XCTAssertEqual(object?.testString, "nil:TestEntity1:10")
defer {
@@ -104,30 +103,30 @@ class ObjectObserverTests: BaseTestDataTestCase {
return events == 1
}
)
let saveExpectation = self.expectationWithDescription("save")
stack.beginAsynchronous { (transaction) in
guard let object = transaction.edit(object) else {
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
XCTFail()
try transaction.cancel()
}
object.testNumber = NSNumber(value: 10)
object.testString = "nil:TestEntity1:10"
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
return
}
object.testNumber = NSNumber(integer: 10)
object.testString = "nil:TestEntity1:10"
transaction.commit { (result) in
switch result {
case .Success(let hasChanges):
XCTAssertTrue(hasChanges)
saveExpectation.fulfill()
case .Failure:
XCTFail()
}
}
}
)
self.waitAndCheckExpectations()
}
}
@@ -140,8 +139,8 @@ class ObjectObserverTests: BaseTestDataTestCase {
self.prepareTestDataForStack(stack)
guard let object = stack.fetchOne(
From(TestEntity1),
Where("testEntityID", isEqualTo: 101)) else {
From<TestEntity1>(),
Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else {
XCTFail()
return
@@ -155,14 +154,14 @@ class ObjectObserverTests: BaseTestDataTestCase {
var events = 0
let didDeleteExpectation = self.expectationForNotification(
"objectMonitor:didDeleteObject:",
let didDeleteExpectation = self.expectation(
forNotification: "objectMonitor:didDeleteObject:",
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual(
(note.userInfo ?? [:]),
((note.userInfo as NSDictionary?) ?? [:]),
["object": object] as NSDictionary
)
defer {
@@ -172,30 +171,30 @@ class ObjectObserverTests: BaseTestDataTestCase {
return events == 0
}
)
let saveExpectation = self.expectationWithDescription("save")
stack.beginAsynchronous { (transaction) in
guard let object = transaction.edit(object) else {
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
XCTFail()
try transaction.cancel()
}
transaction.delete(object)
return transaction.hasChanges
},
success: { (hasChanges) in
XCTAssertTrue(hasChanges)
XCTAssertTrue(monitor.isObjectDeleted)
saveExpectation.fulfill()
},
failure: { _ in
XCTFail()
return
}
transaction.delete(object)
transaction.commit { (result) in
switch result {
case .Success(let hasChanges):
XCTAssertTrue(hasChanges)
XCTAssertTrue(monitor.isObjectDeleted)
saveExpectation.fulfill()
case .Failure:
XCTFail()
}
}
}
)
self.waitAndCheckExpectations()
}
}
@@ -204,14 +203,15 @@ class ObjectObserverTests: BaseTestDataTestCase {
// MARK: TestObjectObserver
@available(OSX 10.12, *)
class TestObjectObserver: ObjectObserver {
typealias ObjectEntityType = TestEntity1
func objectMonitor(monitor: ObjectMonitor<TestEntity1>, willUpdateObject object: TestEntity1) {
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, willUpdateObject object: TestEntity1) {
NSNotificationCenter.defaultCenter().postNotificationName(
"objectMonitor:willUpdateObject:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "objectMonitor:willUpdateObject:"),
object: self,
userInfo: [
"object": object
@@ -219,10 +219,10 @@ class TestObjectObserver: ObjectObserver {
)
}
func objectMonitor(monitor: ObjectMonitor<TestEntity1>, didUpdateObject object: TestEntity1, changedPersistentKeys: Set<KeyPath>) {
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, didUpdateObject object: TestEntity1, changedPersistentKeys: Set<KeyPath>) {
NSNotificationCenter.defaultCenter().postNotificationName(
"objectMonitor:didUpdateObject:changedPersistentKeys:",
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"),
object: self,
userInfo: [
"object": object,
@@ -231,10 +231,10 @@ class TestObjectObserver: ObjectObserver {
)
}
func objectMonitor(monitor: ObjectMonitor<TestEntity1>, didDeleteObject object: TestEntity1) {
func objectMonitor(_ monitor: ObjectMonitor<TestEntity1>, didDeleteObject object: TestEntity1) {
NSNotificationCenter.defaultCenter().postNotificationName(
"objectMonitor:didDeleteObject:",
NotificationCenter.default.post(
name: Notification.Name(rawValue: "objectMonitor:didDeleteObject:"),
object: self,
userInfo: [
"object": object
@@ -242,5 +242,3 @@ class TestObjectObserver: ObjectObserver {
)
}
}
#endif

View File

@@ -39,7 +39,7 @@ final class OrderByTests: XCTestCase {
do {
let orderBy = OrderBy()
XCTAssertEqual(orderBy, OrderBy([] as [NSSortDescriptor]))
XCTAssertEqual(orderBy, OrderBy([NSSortDescriptor]()))
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key", ascending: false)))
XCTAssertTrue(orderBy.sortDescriptors.isEmpty)
}
@@ -48,9 +48,9 @@ final class OrderByTests: XCTestCase {
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
let orderBy = OrderBy(sortDescriptor)
XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Descending("key1")))
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.sortDescriptors, [sortDescriptor])
@@ -63,7 +63,7 @@ final class OrderByTests: XCTestCase {
]
let orderBy = OrderBy(sortDescriptors)
XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2")))
XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual(
orderBy,
OrderBy(
@@ -73,30 +73,30 @@ final class OrderByTests: XCTestCase {
]
)
)
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
}
do {
let orderBy = OrderBy(.Ascending("key1"))
let orderBy = OrderBy(.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(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
}
do {
let orderBy = OrderBy(.Ascending("key1"), .Descending("key2"))
let orderBy = OrderBy(.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(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual(
orderBy,
OrderBy(
@@ -106,20 +106,20 @@ final class OrderByTests: XCTestCase {
]
)
)
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
}
do {
let sortKeys: [SortKey] = [.Ascending("key1"), .Descending("key2")]
let sortKeys: [SortKey] = [.ascending("key1"), .descending("key2")]
let orderBy = OrderBy(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(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual(
orderBy,
OrderBy(
@@ -129,8 +129,8 @@ final class OrderByTests: XCTestCase {
]
)
)
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3")))
XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.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(.ascending("key1"))
let orderBy2 = OrderBy(.descending("key2"))
let orderBy3 = OrderBy(.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(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.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(.ascending("key1"), .descending("key2")))
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.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(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")) + OrderBy(.ascending("key3")))
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
@@ -178,8 +178,8 @@ final class OrderByTests: XCTestCase {
@objc
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
let orderBy = OrderBy(.Ascending("key"))
let request = NSFetchRequest()
let orderBy = OrderBy(.ascending("key"))
let request = CoreStoreFetchRequest()
orderBy.applyToFetchRequest(request)
XCTAssertNotNil(request.sortDescriptors)
XCTAssertEqual(request.sortDescriptors ?? [], orderBy.sortDescriptors)

File diff suppressed because it is too large Load Diff

View File

@@ -29,10 +29,9 @@ import XCTest
import CoreStore
#if os(iOS) || os(watchOS) || os(tvOS)
//MARK: - SectionByTests
@available(OSX 10.12, *)
final class SectionByTests: XCTestCase {
@objc
@@ -42,16 +41,14 @@ final class SectionByTests: XCTestCase {
let sectionBy = SectionBy("key")
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer(sectionName: "key"), "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
}
do {
let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } }
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer(sectionName: "key"), "key:suffix")
XCTAssertNil(sectionBy.sectionIndexTransformer(sectionName: nil))
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
XCTAssertNil(sectionBy.sectionIndexTransformer(nil))
}
}
}
#endif

View File

@@ -39,17 +39,17 @@ final class SelectTests: XCTestCase {
do {
let term: SelectTerm = "attribute"
XCTAssertEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
XCTAssertEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Attribute(let key):
case ._attribute(let key):
XCTAssertEqual(key, "attribute")
default:
@@ -58,17 +58,17 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.Attribute("attribute")
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.attribute("attribute")
XCTAssertNotEqual(term, SelectTerm.attribute("attribute2"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Attribute(let key):
case ._attribute(let key):
XCTAssertEqual(key, "attribute")
default:
@@ -82,23 +82,23 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.Average("attribute")
XCTAssertEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.average("attribute")
XCTAssertEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "average:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "average(attribute)")
XCTAssertTrue(nativeType == .DecimalAttributeType)
XCTAssertTrue(nativeType == .decimalAttributeType)
default:
XCTFail()
@@ -106,23 +106,23 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.Average("attribute", As: "alias")
XCTAssertEqual(term, SelectTerm.Average("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute", As: "alias2"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.average("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.average("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.average("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "average:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "alias")
XCTAssertTrue(nativeType == .DecimalAttributeType)
XCTAssertTrue(nativeType == .decimalAttributeType)
default:
XCTFail()
@@ -135,23 +135,23 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.Count("attribute")
XCTAssertEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.count("attribute")
XCTAssertEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "count:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "count(attribute)")
XCTAssertTrue(nativeType == .Integer64AttributeType)
XCTAssertTrue(nativeType == .integer64AttributeType)
default:
XCTFail()
@@ -159,23 +159,23 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.Count("attribute", As: "alias")
XCTAssertEqual(term, SelectTerm.Count("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute", As: "alias2"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.count("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.count("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.count("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "count:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "alias")
XCTAssertTrue(nativeType == .Integer64AttributeType)
XCTAssertTrue(nativeType == .integer64AttributeType)
default:
XCTFail()
@@ -188,23 +188,23 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.Maximum("attribute")
XCTAssertEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.maximum("attribute")
XCTAssertEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "max:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "max(attribute)")
XCTAssertTrue(nativeType == .UndefinedAttributeType)
XCTAssertTrue(nativeType == .undefinedAttributeType)
default:
XCTFail()
@@ -212,23 +212,23 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.Maximum("attribute", As: "alias")
XCTAssertEqual(term, SelectTerm.Maximum("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute", As: "alias2"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.maximum("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.maximum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "max:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "alias")
XCTAssertTrue(nativeType == .UndefinedAttributeType)
XCTAssertTrue(nativeType == .undefinedAttributeType)
default:
XCTFail()
@@ -241,23 +241,23 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.Minimum("attribute")
XCTAssertEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.minimum("attribute")
XCTAssertEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "min:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "min(attribute)")
XCTAssertTrue(nativeType == .UndefinedAttributeType)
XCTAssertTrue(nativeType == .undefinedAttributeType)
default:
XCTFail()
@@ -265,23 +265,23 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.Minimum("attribute", As: "alias")
XCTAssertEqual(term, SelectTerm.Minimum("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute", As: "alias2"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.minimum("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.minimum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "min:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "alias")
XCTAssertTrue(nativeType == .UndefinedAttributeType)
XCTAssertTrue(nativeType == .undefinedAttributeType)
default:
XCTFail()
@@ -294,23 +294,23 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.Sum("attribute")
XCTAssertEqual(term, SelectTerm.Sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.sum("attribute")
XCTAssertEqual(term, SelectTerm.sum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "sum:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "sum(attribute)")
XCTAssertTrue(nativeType == .DecimalAttributeType)
XCTAssertTrue(nativeType == .decimalAttributeType)
default:
XCTFail()
@@ -318,23 +318,23 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.Sum("attribute", As: "alias")
XCTAssertEqual(term, SelectTerm.Sum("attribute", As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute", As: "alias2"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
let term = SelectTerm.sum("attribute", as: "alias")
XCTAssertEqual(term, SelectTerm.sum("attribute", as: "alias"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute2"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.objectID())
switch term {
case ._Aggregate(let function, let keyPath, let alias, let nativeType):
case ._aggregate(let function, let keyPath, let alias, let nativeType):
XCTAssertEqual(function, "sum:")
XCTAssertEqual(keyPath, "attribute")
XCTAssertEqual(alias, "alias")
XCTAssertTrue(nativeType == .DecimalAttributeType)
XCTAssertTrue(nativeType == .decimalAttributeType)
default:
XCTFail()
@@ -347,20 +347,20 @@ final class SelectTests: XCTestCase {
do {
let term = SelectTerm.ObjectID()
XCTAssertEqual(term, SelectTerm.ObjectID())
XCTAssertNotEqual(term, SelectTerm.ObjectID(As: "alias"))
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
let term = SelectTerm.objectID()
XCTAssertEqual(term, SelectTerm.objectID())
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias"))
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
switch term {
case ._Identity(let alias, let nativeType):
case ._identity(let alias, let nativeType):
XCTAssertEqual(alias, "objectID")
XCTAssertTrue(nativeType == .ObjectIDAttributeType)
XCTAssertTrue(nativeType == .objectIDAttributeType)
default:
XCTFail()
@@ -368,21 +368,21 @@ final class SelectTests: XCTestCase {
}
do {
let term = SelectTerm.ObjectID(As: "alias")
XCTAssertEqual(term, SelectTerm.ObjectID(As: "alias"))
XCTAssertNotEqual(term, SelectTerm.ObjectID(As: "alias2"))
XCTAssertNotEqual(term, SelectTerm.ObjectID())
XCTAssertNotEqual(term, SelectTerm.Attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.Average("attribute"))
XCTAssertNotEqual(term, SelectTerm.Count("attribute"))
XCTAssertNotEqual(term, SelectTerm.Maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.Sum("attribute"))
let term = SelectTerm.objectID(as: "alias")
XCTAssertEqual(term, SelectTerm.objectID(as: "alias"))
XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias2"))
XCTAssertNotEqual(term, SelectTerm.objectID())
XCTAssertNotEqual(term, SelectTerm.attribute("attribute"))
XCTAssertNotEqual(term, SelectTerm.average("attribute"))
XCTAssertNotEqual(term, SelectTerm.count("attribute"))
XCTAssertNotEqual(term, SelectTerm.maximum("attribute"))
XCTAssertNotEqual(term, SelectTerm.minimum("attribute"))
XCTAssertNotEqual(term, SelectTerm.sum("attribute"))
switch term {
case ._Identity(let alias, let nativeType):
case ._identity(let alias, let nativeType):
XCTAssertEqual(alias, "alias")
XCTAssertTrue(nativeType == .ObjectIDAttributeType)
XCTAssertTrue(nativeType == .objectIDAttributeType)
default:
XCTFail()
@@ -393,9 +393,9 @@ 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.attribute("attribute1")
let term2 = SelectTerm.attribute("attribute2")
let term3 = SelectTerm.attribute("attribute3")
do {
let select = Select<Int>(term1, term2, term3)

View File

@@ -29,43 +29,51 @@ import CoreStore
// MARK: - SetupTests
class SetupTests: BaseTestCase {
class SetupTests: BaseTestDataTestCase {
@objc
dynamic func test_ThatDataStacks_ConfigureCorrectly() {
do {
let model = NSManagedObjectModel.mergedModelFromBundles([NSBundle(forClass: self.dynamicType)])!
let stack = DataStack(model: model, migrationChain: nil)
XCTAssertEqual(stack.coordinator.managedObjectModel, model)
let schemaHistory = SchemaHistory(
XcodeDataModelSchema.from(
modelName: "Model",
bundle: Bundle(for: type(of: self))
)
)
let stack = DataStack(schemaHistory: schemaHistory)
XCTAssertEqual(stack.coordinator.managedObjectModel, schemaHistory.rawModel)
XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator)
XCTAssertNil(stack.rootSavingContext.parentContext)
XCTAssertEqual(stack.mainContext.parentContext, stack.rootSavingContext)
XCTAssertEqual(stack.model, model)
XCTAssertTrue(stack.migrationChain.valid)
XCTAssertTrue(stack.migrationChain.empty)
XCTAssertTrue(stack.migrationChain.rootVersions.isEmpty)
XCTAssertTrue(stack.migrationChain.leafVersions.isEmpty)
XCTAssertNil(stack.rootSavingContext.parent)
XCTAssertFalse(stack.rootSavingContext.isDataStackContext)
XCTAssertFalse(stack.rootSavingContext.isTransactionContext)
XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext)
XCTAssertTrue(stack.mainContext.isDataStackContext)
XCTAssertFalse(stack.mainContext.isTransactionContext)
XCTAssertEqual(stack.schemaHistory.rawModel, schemaHistory.rawModel)
XCTAssertTrue(stack.schemaHistory.migrationChain.isValid)
XCTAssertTrue(stack.schemaHistory.migrationChain.isEmpty)
XCTAssertTrue(stack.schemaHistory.migrationChain.rootVersions.isEmpty)
XCTAssertTrue(stack.schemaHistory.migrationChain.leafVersions.isEmpty)
CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack)
}
do {
let migrationChain: MigrationChain = ["version1", "version2", "version3"]
let migrationChain: MigrationChain = ["version1", "version2", "version3", "Model"]
let stack = self.expectLogger([.LogWarning]) {
let stack = self.expectLogger([.logWarning]) {
DataStack(
modelName: "Model",
bundle: NSBundle(forClass: self.dynamicType),
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self)),
migrationChain: migrationChain
)
}
XCTAssertEqual(stack.modelVersion, "Model")
XCTAssertEqual(stack.migrationChain, migrationChain)
XCTAssertEqual(stack.schemaHistory.migrationChain, migrationChain)
CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack)
@@ -76,8 +84,8 @@ class SetupTests: BaseTestCase {
dynamic func test_ThatInMemoryStores_SetupCorrectly() {
let stack = DataStack(
modelName: "Model",
bundle: NSBundle(forClass: self.dynamicType)
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
@@ -131,8 +139,8 @@ class SetupTests: BaseTestCase {
dynamic func test_ThatSQLiteStores_SetupCorrectly() {
let stack = DataStack(
modelName: "Model",
bundle: NSBundle(forClass: self.dynamicType)
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
@@ -154,7 +162,7 @@ class SetupTests: BaseTestCase {
let sqliteStore = SQLiteStore(
fileName: "ConfigStore1.sqlite",
configuration: "Config1",
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
do {
@@ -173,7 +181,7 @@ class SetupTests: BaseTestCase {
let sqliteStore = SQLiteStore(
fileName: "ConfigStore2.sqlite",
configuration: "Config2",
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
do {
@@ -189,16 +197,74 @@ class SetupTests: BaseTestCase {
}
}
@objc
dynamic func test_ThatSQLiteStores_DeleteFilesCorrectly() {
let fileManager = FileManager.default
let sqliteStore = SQLiteStore()
func createStore() throws -> [String: Any] {
do {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try! stack.addStorageAndWait(sqliteStore)
self.prepareTestDataForStack(stack)
}
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: type(of: sqliteStore).storeType,
at: sqliteStore.fileURL,
options: sqliteStore.storeOptions
)
}
do {
let metadata = try createStore()
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try sqliteStore.cs_eraseStorageAndWait(
metadata: metadata,
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
)
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
}
catch {
XCTFail()
}
do {
let metadata = try createStore()
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")))
}
catch {
XCTFail()
}
}
@objc
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
let stack = DataStack(
modelName: "Model",
bundle: NSBundle(forClass: self.dynamicType)
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
do {
let sqliteStore = SQLiteStore()
let sqliteStore = SQLiteStore.legacy()
do {
try stack.addStorageAndWait(sqliteStore)
@@ -213,10 +279,10 @@ class SetupTests: BaseTestCase {
}
do {
let sqliteStore = SQLiteStore(
let sqliteStore = SQLiteStore.legacy(
fileName: "ConfigStore1.sqlite",
configuration: "Config1",
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
do {
@@ -232,10 +298,10 @@ class SetupTests: BaseTestCase {
}
do {
let sqliteStore = SQLiteStore(
let sqliteStore = SQLiteStore.legacy(
fileName: "ConfigStore2.sqlite",
configuration: "Config2",
localStorageOptions: .RecreateStoreOnModelMismatch
localStorageOptions: .recreateStoreOnModelMismatch
)
do {
@@ -250,4 +316,62 @@ class SetupTests: BaseTestCase {
XCTAssert(sqliteStore.matchesPersistentStore(persistentStore!))
}
}
@objc
dynamic func test_ThatLegacySQLiteStores_DeleteFilesCorrectly() {
let fileManager = FileManager.default
let sqliteStore = SQLiteStore.legacy()
func createStore() throws -> [String: Any] {
do {
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try! stack.addStorageAndWait(sqliteStore)
self.prepareTestDataForStack(stack)
}
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
return try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: type(of: sqliteStore).storeType,
at: sqliteStore.fileURL,
options: sqliteStore.storeOptions
)
}
do {
let metadata = try createStore()
let stack = DataStack(
xcodeModelName: "Model",
bundle: Bundle(for: type(of: self))
)
try sqliteStore.cs_eraseStorageAndWait(
metadata: metadata,
soureModelHint: stack.schemaHistory.schema(for: metadata)?.rawModel()
)
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal")))
XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm")))
}
catch {
XCTFail()
}
do {
let metadata = try createStore()
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")))
}
catch {
XCTFail()
}
}
}

View File

@@ -37,7 +37,7 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatDefaultInMemoryStores_ConfigureCorrectly() {
let store = InMemoryStore()
XCTAssertEqual(store.dynamicType.storeType, NSInMemoryStoreType)
XCTAssertEqual(type(of: store).storeType, NSInMemoryStoreType)
XCTAssertNil(store.configuration)
XCTAssertNil(store.storeOptions)
}
@@ -46,7 +46,7 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatCustomInMemoryStores_ConfigureCorrectly() {
let store = InMemoryStore(configuration: "config1")
XCTAssertEqual(store.dynamicType.storeType, NSInMemoryStoreType)
XCTAssertEqual(type(of: store).storeType, NSInMemoryStoreType)
XCTAssertEqual(store.configuration, "config1")
XCTAssertNil(store.storeOptions)
}
@@ -55,24 +55,23 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatSQLiteStoreDefaultDirectories_AreCorrect() {
#if os(tvOS)
let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory
let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
#else
let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory
let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory
#endif
let defaultSystemDirectory = NSFileManager
.defaultManager()
.URLsForDirectory(systemDirectorySearchPath, inDomains: .UserDomainMask).first!
let defaultSystemDirectory = FileManager.default
.urls(for: systemDirectorySearchPath, in: .userDomainMask).first!
let defaultRootDirectory = defaultSystemDirectory.URLByAppendingPathComponent(
NSBundle.mainBundle().bundleIdentifier ?? "com.CoreStore.DataStack",
let defaultRootDirectory = defaultSystemDirectory.appendingPathComponent(
Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack",
isDirectory: true
)
let applicationName = (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData"
let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData"
let defaultFileURL = defaultRootDirectory
.URLByAppendingPathComponent(applicationName, isDirectory: false)
.URLByAppendingPathExtension("sqlite")
.appendingPathComponent(applicationName, isDirectory: false)
.appendingPathExtension("sqlite")
XCTAssertEqual(SQLiteStore.defaultRootDirectory, defaultRootDirectory)
XCTAssertEqual(SQLiteStore.defaultFileURL, defaultFileURL)
@@ -82,137 +81,120 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatDefaultSQLiteStores_ConfigureCorrectly() {
let store = SQLiteStore()
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertNil(store.configuration)
XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.fileURL, SQLiteStore.defaultFileURL)
XCTAssertEqual(store.mappingModelBundles, NSBundle.allBundles())
XCTAssertEqual(store.localStorageOptions, [.None])
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
XCTAssertEqual(store.localStorageOptions, .none)
}
@objc
dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() {
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
.URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)
.URLByAppendingPathExtension("db")
let bundles = [NSBundle(forClass: self.dynamicType)]
.appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
.appendingPathExtension("db")
let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
)
let store = SQLiteStore(
fileURL: fileURL,
configuration: "config1",
mappingModelBundles: bundles,
localStorageOptions: .RecreateStoreOnModelMismatch
migrationMappingProviders: [mappingProvider],
localStorageOptions: .recreateStoreOnModelMismatch
)
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.fileURL, fileURL)
XCTAssertEqual(store.mappingModelBundles, bundles)
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch])
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
}
@objc
dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() {
let fileName = NSUUID().UUIDString + ".db"
let bundles = [NSBundle(forClass: self.dynamicType)]
let fileName = UUID().uuidString + ".db"
let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
)
let store = SQLiteStore(
fileName: fileName,
configuration: "config1",
mappingModelBundles: bundles,
localStorageOptions: .RecreateStoreOnModelMismatch
migrationMappingProviders: [mappingProvider],
localStorageOptions: .recreateStoreOnModelMismatch
)
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.fileURL.URLByDeletingLastPathComponent, SQLiteStore.defaultRootDirectory)
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.defaultRootDirectory)
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
XCTAssertEqual(store.mappingModelBundles, bundles)
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch])
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
}
@objc
dynamic func test_ThatLegacySQLiteStoreDefaultDirectories_AreCorrect() {
#if os(tvOS)
let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory
let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
#else
let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory
let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory
#endif
let legacyDefaultRootDirectory = NSFileManager.defaultManager().URLsForDirectory(
systemDirectorySearchPath,
inDomains: .UserDomainMask
).first!
let legacyDefaultRootDirectory = FileManager.default.urls(
for: systemDirectorySearchPath,
in: .userDomainMask).first!
let legacyDefaultFileURL = legacyDefaultRootDirectory
.URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false)
.URLByAppendingPathExtension("sqlite")
.appendingPathComponent(DataStack.applicationName, isDirectory: false)
.appendingPathExtension("sqlite")
XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory)
XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL)
XCTAssertEqual(SQLiteStore.legacyDefaultRootDirectory, legacyDefaultRootDirectory)
XCTAssertEqual(SQLiteStore.legacyDefaultFileURL, legacyDefaultFileURL)
}
@objc
dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() {
let store = LegacySQLiteStore()
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType)
let store = SQLiteStore.legacy()
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertNil(store.configuration)
XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.fileURL, LegacySQLiteStore.defaultFileURL)
XCTAssertEqual(store.mappingModelBundles, NSBundle.allBundles())
XCTAssertEqual(store.localStorageOptions, [.None])
}
@objc
dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() {
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
.URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)
.URLByAppendingPathExtension("db")
let bundles = [NSBundle(forClass: self.dynamicType)]
let store = LegacySQLiteStore(
fileURL: fileURL,
configuration: "config1",
mappingModelBundles: bundles,
localStorageOptions: .RecreateStoreOnModelMismatch
)
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.fileURL, fileURL)
XCTAssertEqual(store.mappingModelBundles, bundles)
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch])
XCTAssertEqual(store.fileURL, SQLiteStore.legacyDefaultFileURL)
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
XCTAssertEqual(store.localStorageOptions, .none)
}
@objc
dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() {
let fileName = NSUUID().UUIDString + ".db"
let bundles = [NSBundle(forClass: self.dynamicType)]
let store = LegacySQLiteStore(
let fileName = UUID().uuidString + ".db"
let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
)
let store = SQLiteStore.legacy(
fileName: fileName,
configuration: "config1",
mappingModelBundles: bundles,
localStorageOptions: .RecreateStoreOnModelMismatch
migrationMappingProviders: [mappingProvider],
localStorageOptions: .recreateStoreOnModelMismatch
)
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary)
XCTAssertEqual(store.fileURL.URLByDeletingLastPathComponent, LegacySQLiteStore.defaultRootDirectory)
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.legacyDefaultRootDirectory)
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
XCTAssertEqual(store.mappingModelBundles, bundles)
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch])
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
}
}

View File

@@ -31,9 +31,9 @@ class TestEntity1: NSManagedObject {
@NSManaged var testEntityID: NSNumber?
@NSManaged var testString: String?
@NSManaged var testNumber: NSNumber?
@NSManaged var testDate: NSDate?
@NSManaged var testDate: Date?
@NSManaged var testBoolean: NSNumber?
@NSManaged var testDecimal: NSDecimalNumber?
@NSManaged var testData: NSData?
@NSManaged var testData: Data?
@NSManaged var testNil: String?
}

View File

@@ -31,9 +31,9 @@ class TestEntity2: NSManagedObject {
@NSManaged var testEntityID: NSNumber?
@NSManaged var testString: String?
@NSManaged var testNumber: NSNumber?
@NSManaged var testDate: NSDate?
@NSManaged var testDate: Date?
@NSManaged var testBoolean: NSNumber?
@NSManaged var testDecimal: NSDecimalNumber?
@NSManaged var testData: NSData?
@NSManaged var testData: Data?
@NSManaged var testNil: String?
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -29,6 +29,25 @@ import XCTest
import CoreStore
// MARK: - XCTAssertAllEqual
private func XCTAssertAllEqual(_ whereClauses: Where...) {
XCTAssertAllEqual(whereClauses)
}
private func XCTAssertAllEqual(_ whereClauses: [Where]) {
for i in whereClauses.indices {
for j in whereClauses.indices where j != i {
XCTAssertEqual(whereClauses[i], whereClauses[j])
}
}
}
//MARK: - WhereTests
final class WhereTests: XCTestCase {
@@ -87,6 +106,123 @@ final class WhereTests: XCTestCase {
}
}
@objc
dynamic func test_ThatWhereClauses_BridgeArgumentsCorrectly() {
do {
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))
)
}
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)
)
}
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))
)
}
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)
)
}
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))
)
}
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)
)
}
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)
)
}
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)
)
}
}
@objc
dynamic func test_ThatWhereClauseOperations_ComputeCorrectly() {
@@ -98,7 +234,7 @@ final class WhereTests: XCTestCase {
let notWhere = !whereClause1
let notPredicate = NSCompoundPredicate(
type: .NotPredicateType,
type: .not,
subpredicates: [whereClause1.predicate]
)
XCTAssertEqual(notWhere.predicate, notPredicate)
@@ -108,10 +244,10 @@ final class WhereTests: XCTestCase {
let andWhere = whereClause1 && whereClause2 && whereClause3
let andPredicate = NSCompoundPredicate(
type: .AndPredicateType,
type: .and,
subpredicates: [
NSCompoundPredicate(
type: .AndPredicateType,
type: .and,
subpredicates: [whereClause1.predicate, whereClause2.predicate]
),
whereClause3.predicate
@@ -124,10 +260,10 @@ final class WhereTests: XCTestCase {
let orWhere = whereClause1 || whereClause2 || whereClause3
let orPredicate = NSCompoundPredicate(
type: .OrPredicateType,
type: .or,
subpredicates: [
NSCompoundPredicate(
type: .OrPredicateType,
type: .or,
subpredicates: [whereClause1.predicate, whereClause2.predicate]
),
whereClause3.predicate
@@ -142,7 +278,7 @@ final class WhereTests: XCTestCase {
dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() {
let whereClause = Where("key", isEqualTo: "value")
let request = NSFetchRequest()
let request = CoreStoreFetchRequest()
whereClause.applyToFetchRequest(request)
XCTAssertNotNil(request.predicate)
XCTAssertEqual(request.predicate, whereClause.predicate)

View File

@@ -41,11 +41,5 @@ targets = []
let package = Package(
name: "CoreStore",
targets: targets,
dependencies: [
.Package(
url: "https://github.com/JohnEstropia/GCDKit.git",
majorVersion: 1, minor: 2
)
],
exclude: ["Carthage", "CoreStoreDemo", "Sources/libA/images"]
)

1113
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,274 @@
//
// AsynchronousDataTransaction.swift
// CoreStore
//
// Copyright © 2015 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - AsynchronousDataTransaction
/**
The `AsynchronousDataTransaction` provides an interface for `DynamicObject` creates, updates, and deletes. A transaction object should typically be only used from within a transaction block initiated from `DataStack.perform(asynchronous:...)`, or from `CoreStore.perform(synchronous:...)`.
*/
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 {
case .success: return true
case .failure: return false
}
}
// MARK: Internal
internal init(userInfo: T) {
self = .success(userInfo: userInfo)
}
internal init(error: CoreStoreError) {
self = .failure(error: error)
}
}
// MARK: -
// MARK: BaseDataTransaction
/**
Creates a new `NSManagedObject` or `CoreStoreObject` with the specified entity type.
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/
public override func create<T: DynamicObject>(_ into: Into<T>) -> T {
CoreStore.assert(
!self.isCommitted,
"Attempted to create an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
)
return super.create(into)
}
/**
Returns an editable proxy of a specified `NSManagedObject` or `CoreStoreObject`.
- 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? {
CoreStore.assert(
!self.isCommitted,
"Attempted to update an entity of type \(cs_typeName(object)) from an already committed \(cs_typeName(self))."
)
return super.edit(object)
}
/**
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` or `CoreStoreObject`.
*/
public override func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
!self.isCommitted,
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
)
return super.edit(into, objectID)
}
/**
Deletes a specified `NSManagedObject` or `CoreStoreObject`.
- parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted
*/
public override func delete<T: DynamicObject>(_ object: T?) {
CoreStore.assert(
!self.isCommitted,
"Attempted to delete an entity of type \(cs_typeName(object)) from an already committed \(cs_typeName(self))."
)
super.delete(object)
}
/**
Deletes the specified `DynamicObject`s.
- parameter object1: the `DynamicObject` to be deleted
- parameter object2: another `DynamicObject` to be deleted
- parameter objects: other `DynamicObject`s to be deleted
*/
public override func delete<T: DynamicObject>(_ object1: T?, _ object2: T?, _ objects: T?...) {
CoreStore.assert(
!self.isCommitted,
"Attempted to delete an entities from an already committed \(cs_typeName(self))."
)
super.delete(([object1, object2] + objects).flatMap { $0 })
}
/**
Deletes the specified `DynamicObject`s.
- parameter objects: the `DynamicObject`s to be deleted
*/
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
CoreStore.assert(
!self.isCommitted,
"Attempted to delete an entities from an already committed \(cs_typeName(self))."
)
super.delete(objects)
}
// MARK: Internal
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue) {
super.init(mainContext: mainContext, queue: queue, supportsUndo: false, bypassesQueueing: false)
}
internal func autoCommit(_ completion: @escaping (_ hasChanges: Bool, _ error: CoreStoreError?) -> Void) {
self.isCommitted = true
let group = DispatchGroup()
group.enter()
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
completion(result.0, result.1)
self.result = result
group.leave()
}
group.wait()
}
// MARK: Deprecated
@available(*, deprecated, message: "Use the new auto-commiting methods `DataStack.perform(asynchronous:completion:)` or `DataStack.perform(asynchronous:success:failure:)`. Please read the documentation on the behavior of the new methods.")
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.autoCommit { (result) in
switch result {
case (let hasChanges, nil): completion(SaveResult(hasChanges: hasChanges))
case (_, let error?): completion(SaveResult(error))
}
}
}
@available(*, deprecated, message: "Secondary tasks spawned from AsynchronousDataTransactions and SynchronousDataTransactions are no longer supported. ")
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
CoreStore.assert(
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to begin a child transaction from an already committed \(cs_typeName(self))."
)
let childTransaction = SynchronousDataTransaction(
mainContext: self.context,
queue: self.childTransactionQueue
)
childTransaction.transactionQueue.cs_sync {
closure(childTransaction)
if !childTransaction.isCommitted && childTransaction.hasChanges {
CoreStore.log(
.warning,
message: "The closure for the \(cs_typeName(childTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
}
switch childTransaction.result {
case nil: return nil
case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges)
case (_, let error?)?: return SaveResult(error)
}
}
}

View File

@@ -36,27 +36,28 @@ public extension BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type
- parameter source: the object to import values from
- throws: an `ErrorType` thrown from any of the `ImportableObject` methods
- throws: an `Error` thrown from any of the `ImportableObject` methods
- returns: the created `ImportableObject` instance, or `nil` if the import was ignored
*/
public func importObject<T where T: NSManagedObject, T: ImportableObject>(
into: Into<T>,
public func importObject<T: DynamicObject & ImportableObject>(
_ into: Into<T>,
source: T.ImportSource) throws -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
)
return try cs_autoreleasepool {
return try autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
let entityType = into.entityClass
guard entityType.shouldInsert(from: source, in: self) else {
return nil
}
let object = self.create(into)
try object.didInsertFromImportSource(source, inTransaction: self)
try object.didInsert(from: source, in: self)
return object
}
}
@@ -66,10 +67,10 @@ public extension BaseDataTransaction {
- parameter object: the `NSManagedObject` to update
- parameter source: the object to import values from
- throws: an `ErrorType` thrown from any of the `ImportableObject` methods
- throws: an `Error` thrown from any of the `ImportableObject` methods
*/
public func importObject<T where T: NSManagedObject, T: ImportableObject>(
object: T,
public func importObject<T: DynamicObject & ImportableObject>(
_ object: T,
source: T.ImportSource) throws {
CoreStore.assert(
@@ -77,14 +78,14 @@ public extension BaseDataTransaction {
"Attempted to import an object of type \(cs_typeName(object)) outside the transaction's designated queue."
)
try cs_autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
try autoreleasepool {
let entityType = type(of: object)
guard entityType.shouldInsert(from: source, in: self) else {
return
}
try object.didInsertFromImportSource(source, inTransaction: self)
try object.didInsert(from: source, in: self)
}
}
@@ -93,31 +94,31 @@ public extension BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type
- parameter sourceArray: the array of objects to import values from
- throws: an `ErrorType` thrown from any of the `ImportableObject` methods
- throws: an `Error` thrown from any of the `ImportableObject` methods
- returns: the array of created `ImportableObject` instances
*/
public func importObjects<T, S: SequenceType where T: NSManagedObject, T: ImportableObject, S.Generator.Element == T.ImportSource>(
into: Into<T>,
sourceArray: S) throws -> [T] {
public func importObjects<T: DynamicObject & ImportableObject, S: Sequence>(
_ into: Into<T>,
sourceArray: S) throws -> [T] where S.Iterator.Element == T.ImportSource {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
)
return try cs_autoreleasepool {
return try autoreleasepool {
return try sourceArray.flatMap { (source) -> T? in
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
let entityType = into.entityClass
guard entityType.shouldInsert(from: source, in: self) else {
return nil
}
return try cs_autoreleasepool {
return try autoreleasepool {
let object = self.create(into)
try object.didInsertFromImportSource(source, inTransaction: self)
try object.didInsert(from: source, in: self)
return object
}
}
@@ -129,46 +130,45 @@ public extension BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type
- parameter source: the object to import values from
- throws: an `ErrorType` thrown from any of the `ImportableUniqueObject` methods
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
- returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
*/
public func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>(
into: Into<T>,
source: T.ImportSource) throws -> T? {
public func importUniqueObject<T: DynamicObject & ImportableUniqueObject>(
_ into: Into<T>,
source: T.ImportSource) throws -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
)
return try cs_autoreleasepool {
let uniqueIDKeyPath = T.uniqueIDKeyPath
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
return try autoreleasepool {
let entityType = into.entityClass
let uniqueIDKeyPath = entityType.uniqueIDKeyPath
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
return nil
}
if let object = self.fetchOne(From(T), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
if let object = self.fetchOne(From(entityType), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
guard T.shouldUpdateFromImportSource(source, inTransaction: self) else {
guard entityType.shouldUpdate(from: source, in: self) else {
return nil
}
try object.updateFromImportSource(source, inTransaction: self)
try object.update(from: source, in: self)
return object
}
else {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
guard entityType.shouldInsert(from: source, in: self) else {
return nil
}
let object = self.create(into)
object.uniqueIDValue = uniqueIDValue
try object.didInsertFromImportSource(source, inTransaction: self)
try object.didInsert(from: source, in: self)
return object
}
}
@@ -176,79 +176,79 @@ public extension BaseDataTransaction {
/**
Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources.
- Warning: While the array returned from `importUniqueObjects(...)` correctly maps to the order of `sourceArray`, the order of objects called with `ImportableUniqueObject` methods is arbitrary. Do not make assumptions that any particular object will be imported ahead or after another object.
`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, 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
- parameter preProcess: a closure that lets the caller tweak the internal `UniqueIDType`-to-`ImportSource` mapping to be used for importing. Callers can remove from/add to/update `mapping` and return the updated array from the closure.
- throws: an `ErrorType` thrown from any of the `ImportableUniqueObject` methods
- throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
- returns: the array of created/updated `ImportableUniqueObject` instances
*/
public func importUniqueObjects<T, S: SequenceType where T: NSManagedObject, T: ImportableUniqueObject, S.Generator.Element == T.ImportSource>(
into: Into<T>,
public func importUniqueObjects<T: DynamicObject & ImportableUniqueObject, S: Sequence>(
_ into: Into<T>,
sourceArray: S,
@noescape preProcess: (mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] {
preProcess: @escaping (_ mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] where S.Iterator.Element == T.ImportSource {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
)
return try cs_autoreleasepool {
var mapping = Dictionary<T.UniqueIDType, T.ImportSource>()
let sortedIDs = try cs_autoreleasepool {
return try autoreleasepool {
let entityType = into.entityClass
var importSourceByID = Dictionary<T.UniqueIDType, T.ImportSource>()
let sortedIDs = try autoreleasepool {
return try sourceArray.flatMap { (source) -> T.UniqueIDType? in
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
return nil
}
mapping[uniqueIDValue] = source
importSourceByID[uniqueIDValue] = source // effectively replaces duplicate with the latest
return uniqueIDValue
}
}
mapping = try cs_autoreleasepool { try preProcess(mapping: mapping) }
var objects = Dictionary<T.UniqueIDType, T>()
for object in self.fetchAll(From(T), Where(T.uniqueIDKeyPath, isMemberOf: sortedIDs)) ?? [] {
importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
var existingObjectsByID = Dictionary<T.UniqueIDType, T>()
self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
var processedObjectIDs = Set<T.UniqueIDType>()
var result = [T]()
for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
try cs_autoreleasepool {
guard let source = importSourceByID[objectID] else {
let uniqueIDValue = object.uniqueIDValue
guard let source = mapping.removeValueForKey(uniqueIDValue)
where T.shouldUpdateFromImportSource(source, inTransaction: self) else {
continue
}
try autoreleasepool {
if let object = existingObjectsByID[objectID] {
guard entityType.shouldUpdate(from: source, in: self) else {
return
}
try object.update(from: source, in: self)
result.append(object)
}
try object.updateFromImportSource(source, inTransaction: self)
objects[uniqueIDValue] = object
}
}
for (uniqueIDValue, source) in mapping {
try cs_autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
else if entityType.shouldInsert(from: source, in: self) {
return
let object = self.create(into)
object.uniqueIDValue = objectID
try object.didInsert(from: source, in: self)
result.append(object)
}
let object = self.create(into)
object.uniqueIDValue = uniqueIDValue
try object.didInsertFromImportSource(source, inTransaction: self)
objects[uniqueIDValue] = object
processedObjectIDs.insert(objectID)
}
}
return sortedIDs.flatMap { objects[$0] }
return result
}
}
}

View File

@@ -29,92 +29,99 @@ import CoreData
// MARK: - DataTransaction
public extension BaseDataTransaction {
extension BaseDataTransaction: FetchableSource, QueryableSource {
/**
Fetches the `NSManagedObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
Deletes all `DynamicObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.deleteAll(from, deleteClauses)
}
/**
Deletes all `DynamicObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number of `DynamicObject`s deleted
*/
@discardableResult
public func deleteAll<T: DynamicObject>(_ from: From<T>, _ 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)
}
// MARK: FetchableSource
/**
Fetches the `DynamicObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
- parameter object: a reference to the object created/fetched outside the transaction
- returns: the `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.
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject>(object: T) -> T? {
public func fetchExisting<T: DynamicObject>(_ object: T) -> T? {
do {
return (try self.context.existingObjectWithID(object.objectID) as! T)
}
catch _ {
return nil
}
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.
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
public func fetchExisting<T: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
do {
return (try self.context.existingObjectWithID(objectID) as! T)
}
catch _ {
return nil
}
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
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == T>(objects: S) -> [T] {
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
return objects.flatMap { (try? self.context.existingObjectWithID($0.objectID)) as? T }
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
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == NSManagedObjectID>(objectIDs: S) -> [T] {
public func fetchExisting<T: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
return objectIDs.flatMap { (try? self.context.existingObjectWithID($0)) as? T }
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
*/
@warn_unused_result
public func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? {
return self.fetchOne(from, fetchClauses)
}
/**
Fetches the first `NSManagedObject` 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
*/
@warn_unused_result
public func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -124,27 +131,29 @@ public extension BaseDataTransaction {
}
/**
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 `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: the first `DynamicObject` instance that satisfies the specified `FetchClause`s
*/
@warn_unused_result
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
public func fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
return self.fetchAll(from, fetchClauses)
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchOne(from, fetchClauses)
}
/**
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
*/
@warn_unused_result
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -154,58 +163,61 @@ public extension BaseDataTransaction {
}
/**
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 `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: all `DynamicObject` instances that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
return self.fetchCount(from, fetchClauses)
}
/**
Fetches the number of `NSManagedObject`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
*/
@warn_unused_result
public func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
public func fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchAll(from, fetchClauses)
}
/**
Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchCount(from, fetchClauses)
}
/**
Fetches the `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 `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 number `DynamicObject`s that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
public func fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
return self.fetchObjectID(from, fetchClauses)
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchCount(from, fetchClauses)
}
/**
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
*/
@warn_unused_result
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -215,27 +227,29 @@ public extension BaseDataTransaction {
}
/**
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 `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 the first `DynamicObject` that satisfies the specified `FetchClause`s
*/
@warn_unused_result
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
public func fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
return self.fetchObjectIDs(from, fetchClauses)
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.fetchObjectID(from, fetchClauses)
}
/**
Fetches the `NSManagedObjectID` for 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
*/
@warn_unused_result
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -245,38 +259,23 @@ public extension BaseDataTransaction {
}
/**
Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`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 deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number of `NSManagedObject`s deleted
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s
*/
public func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
public func fetchObjectIDs<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.deleteAll(from, deleteClauses)
return self.context.fetchObjectIDs(from, fetchClauses)
}
/**
Deletes all `NSManagedObject`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
*/
public func deleteAll<T: NSManagedObject>(from: From<T>, _ 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)
}
// MARK: QueryableSource
/**
Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
@@ -288,14 +287,12 @@ public extension BaseDataTransaction {
- 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.
*/
@warn_unused_result
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.queryValue(from, selectClause, queryClauses)
}
@@ -309,14 +306,12 @@ public extension BaseDataTransaction {
- 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.
*/
@warn_unused_result
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
public func queryValue<T: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.queryValue(from, selectClause, queryClauses)
}
@@ -330,14 +325,12 @@ public extension BaseDataTransaction {
- 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.
*/
@warn_unused_result
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.queryAttributes(from, selectClause, queryClauses)
}
@@ -351,14 +344,32 @@ public extension BaseDataTransaction {
- 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.
*/
@warn_unused_result
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
public func queryAttributes<T: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue."
)
return self.context.queryAttributes(from, selectClause, queryClauses)
}
// MARK: FetchableSource, QueryableSource
/**
The internal `NSManagedObjectContext` managed by this instance. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
*/
public func unsafeContext() -> NSManagedObjectContext {
return self.context
}
// MARK: Obsoleted
@available(*, obsoleted: 3.1, renamed: "unsafeContext()")
public func internalContext() -> NSManagedObjectContext {
fatalError()
}
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - BaseDataTransaction
@@ -48,32 +45,36 @@ public /*abstract*/ class BaseDataTransaction {
}
/**
Creates a new `NSManagedObject` with the specified entity type.
Creates a new `NSManagedObject` or `CoreStoreObject` with the specified entity type.
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type.
- parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/
public func create<T: NSManagedObject>(into: Into<T>) -> T {
public func create<T: DynamicObject>(_ into: Into<T>) -> T {
let entityClass = into.entityClass
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to create an entity of type \(cs_typeName(T)) outside its designated queue."
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
)
let context = self.context
let entityClass = (into.entityClass as! NSManagedObject.Type)
let dataStack = context.parentStack!
let entityIdentifier = EntityIdentifier(entityClass)
if into.inferStoreIfPossible {
switch context.parentStack!.persistentStoreForEntityClass(
entityClass,
switch dataStack.persistentStore(
for: entityIdentifier,
configuration: nil,
inferStoreIfPossible: true
) {
case (let persistentStore?, _):
let object = entityClass.createInContext(context) as! T
context.assignObject(object, toPersistentStore: persistentStore)
return object
return entityClass.cs_forceCreate(
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
into: context,
assignTo: persistentStore
)
case (nil, true):
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
@@ -84,17 +85,19 @@ public /*abstract*/ class BaseDataTransaction {
}
else {
switch context.parentStack!.persistentStoreForEntityClass(
entityClass,
switch dataStack.persistentStore(
for: entityIdentifier,
configuration: into.configuration
?? into.dynamicType.defaultConfigurationName,
?? DataStack.defaultConfigurationName,
inferStoreIfPossible: false
) {
case (let persistentStore?, _):
let object = entityClass.createInContext(context) as! T
context.assignObject(object, toPersistentStore: persistentStore)
return object
return entityClass.cs_forceCreate(
entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
into: context,
assignTo: persistentStore
)
case (nil, true):
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
@@ -118,8 +121,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public func edit<T: NSManagedObject>(object: T?) -> T? {
public func edit<T: DynamicObject>(_ object: T?) -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -139,19 +141,18 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to update an entity of type \(cs_typeName(T)) outside its designated queue."
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) outside its designated queue."
)
CoreStore.assert(
into.inferStoreIfPossible
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
"Attempted to update an entity of type \(cs_typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`."
|| (into.configuration ?? DataStack.defaultConfigurationName) == objectID.persistentStore?.configurationName,
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
)
return self.fetchExisting(objectID) as? T
return self.fetchExisting(objectID)
}
/**
@@ -159,17 +160,16 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` to be deleted
*/
public func delete(object: NSManagedObject?) {
public func delete<T: DynamicObject>(_ object: T?) {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete an entity outside its designated queue."
)
guard let object = object else {
return
}
self.context.fetchExisting(object)?.deleteFromContext()
let context = self.context
object
.flatMap(context.fetchExisting)
.flatMap({ context.delete($0.cs_toRaw()) })
}
/**
@@ -179,7 +179,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object2: another `NSManagedObject` to be deleted
- parameter objects: other `NSManagedObject`s to be deleted
*/
public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
public func delete<T: DynamicObject>(_ object1: T?, _ object2: T?, _ objects: T?...) {
self.delete(([object1, object2] + objects).flatMap { $0 })
}
@@ -189,15 +189,14 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objects: the `NSManagedObject`s to be deleted
*/
public func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: DynamicObject {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to delete entities outside their designated queue."
)
let context = self.context
objects.forEach { context.fetchExisting($0)?.deleteFromContext() }
objects.forEach { context.fetchExisting($0).flatMap({ context.delete($0.cs_toRaw()) }) }
}
/**
@@ -209,7 +208,6 @@ public /*abstract*/ class BaseDataTransaction {
self.isRunningInAllowedQueue(),
"Attempted to refresh entities outside their designated queue."
)
self.context.refreshAndMergeAllObjects()
}
@@ -217,44 +215,22 @@ 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.
*/
@warn_unused_result
public func insertedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.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.
*/
@warn_unused_result
public func insertedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
public func insertedObjects<T: DynamicObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access inserted objects from an already committed \(cs_typeName(self))."
)
return Set(self.context.insertedObjects.flatMap { $0 as? T })
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
/**
@@ -262,81 +238,55 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObjectID`s that were inserted to the transaction.
*/
@warn_unused_result
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.insertedObjects.map { $0.objectID })
}
/**
Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- 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.
*/
@warn_unused_result
public func insertedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
public func insertedObjectIDs<T: DynamicObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.insertedObjects.filter { $0.isKindOfClass(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.
*/
@warn_unused_result
public func updatedObjects() -> Set<NSManagedObject> {
public func updatedObjects<T: DynamicObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
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
}
/**
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.
*/
@warn_unused_result
public func updatedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.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.isKindOfClass(entity) }.map { $0 as! T })
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
}
/**
@@ -344,144 +294,127 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObjectID`s that were updated in the transaction.
*/
@warn_unused_result
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.updatedObjects.map { $0.objectID })
}
/**
Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- 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.
*/
@warn_unused_result
public func updatedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
public func updatedObjectIDs<T: DynamicObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.updatedObjects.filter { $0.isKindOfClass(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.
*/
@warn_unused_result
public func deletedObjects() -> Set<NSManagedObject> {
public func deletedObjects<T: DynamicObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
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
}
/**
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.
*/
@warn_unused_result
public func deletedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.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.isKindOfClass(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.
*/
@warn_unused_result
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.deletedObjects.map { $0.objectID })
}
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- 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.
*/
@warn_unused_result
public func deletedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
public func deletedObjectIDs<T: DynamicObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.isCommitted,
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
}
// MARK: 3rd Party Utilities
/**
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
transaction.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
*/
public let userInfo = UserInfo()
// MARK: Internal
internal let context: NSManagedObjectContext
internal let transactionQueue: GCDQueue
internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue")
internal let transactionQueue: DispatchQueue
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childTransactionQueue")
internal let supportsUndo: Bool
internal let bypassesQueueing: Bool
internal var isCommitted = false
internal var result: SaveResult?
internal var result: (hasChanges: Bool, error: CoreStoreError?)?
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
let context = mainContext.temporaryContextInTransactionWithConcurrencyType(
queue == .Main
? .MainQueueConcurrencyType
: .PrivateQueueConcurrencyType
queue == .main
? .mainQueueConcurrencyType
: .privateQueueConcurrencyType
)
self.transactionQueue = queue
self.context = context
@@ -489,18 +422,64 @@ public /*abstract*/ class BaseDataTransaction {
self.bypassesQueueing = bypassesQueueing
context.parentTransaction = self
context.isTransactionContext = true
if !supportsUndo {
context.undoManager = nil
}
else if context.undoManager == nil {
context.undoManager = NSUndoManager()
context.undoManager = UndoManager()
}
}
internal func isRunningInAllowedQueue() -> Bool {
return self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext()
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
}
// 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,36 +35,31 @@ 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 commitWithCompletion(completion: ((result: CSSaveResult) -> Void)?) {
public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
self.bridgeToSwift.commit { (result) in
CoreStore.assert(
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.bridgeToSwift.autoCommit { (result) in
completion?(result: result.bridgeToObjectiveC)
}
}
/**
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/
@objc
public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return bridge {
self.bridgeToSwift.beginSynchronous { (transaction) in
switch result {
closure(transaction: transaction.bridgeToObjectiveC)
case (_, nil): success?()
case (_, let error?): failure?(error.bridgeToObjectiveC)
}
}
}
@@ -74,7 +69,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -87,7 +82,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
@objc
public override func createInto(into: CSInto) -> AnyObject {
public override func createInto(_ into: CSInto) -> Any {
return self.bridgeToSwift.create(into.bridgeToSwift)
}
@@ -99,8 +94,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc
@warn_unused_result
public override func editObject(object: NSManagedObject?) -> AnyObject? {
public override func editObject(_ object: NSManagedObject?) -> Any? {
return self.bridgeToSwift.edit(object)
}
@@ -113,8 +107,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc
@warn_unused_result
public override func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
public override func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
}
@@ -125,7 +118,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- parameter object: the `NSManagedObject` type to be deleted
*/
@objc
public override func deleteObject(object: NSManagedObject?) {
public override func deleteObject(_ object: NSManagedObject?) {
self.bridgeToSwift.delete(object)
}
@@ -136,7 +129,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- parameter objects: the `NSManagedObject`s type to be deleted
*/
@objc
public override func deleteObjects(objects: [NSManagedObject]) {
public override func deleteObjects(_ objects: [NSManagedObject]) {
self.bridgeToSwift.delete(objects)
}
@@ -144,30 +137,68 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
// MARK: CoreStoreObjectiveCType
internal typealias SwiftType = AsynchronousDataTransaction
public typealias SwiftType = AsynchronousDataTransaction
public override var bridgeToSwift: AsynchronousDataTransaction {
public var bridgeToSwift: AsynchronousDataTransaction {
return super.bridgeToSwift as! AsynchronousDataTransaction
return super.swiftTransaction as! AsynchronousDataTransaction
}
public required init(_ swiftValue: AsynchronousDataTransaction) {
super.init(swiftValue as BaseDataTransaction)
}
public required override init(_ swiftValue: BaseDataTransaction) {
super.init(swiftValue)
}
public required init(_ swiftValue: BaseDataTransaction) {
// MARK: Deprecated
@available(*, deprecated, message: "Use the new -[CSAsynchronousDataTransaction commitWithSuccess:failure:] method.")
@objc
public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
fatalError("init(_:) requires an AsynchronousDataTransaction instance")
CoreStore.assert(
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.bridgeToSwift.commit { (result) in
completion?(result.bridgeToObjectiveC)
}
}
@available(*, deprecated, message: "Secondary tasks spawned from CSAsynchronousDataTransactions and CSSynchronousDataTransactions are no longer supported. ")
@objc
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return bridge {
self.bridgeToSwift.beginSynchronous { (transaction) in
closure(transaction.bridgeToObjectiveC)
}
}
}
}
// MARK: - AsynchronousDataTransaction
extension AsynchronousDataTransaction {
extension AsynchronousDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
internal typealias ObjectiveCType = CSAsynchronousDataTransaction
public var bridgeToObjectiveC: CSAsynchronousDataTransaction {
return CSAsynchronousDataTransaction(self)
}
}

View File

@@ -38,17 +38,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc
@warn_unused_result
public func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
do {
return try self.bridgeToSwift.context.existingObjectWithID(object.objectID)
}
catch _ {
return nil
}
return self.swiftTransaction.context.fetchExisting(object) as NSManagedObject?
}
/**
@@ -58,17 +50,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc
@warn_unused_result
public func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
do {
return try self.bridgeToSwift.context.existingObjectWithID(objectID)
}
catch _ {
return nil
}
return self.swiftTransaction.context.fetchExisting(objectID) as NSManagedObject?
}
/**
@@ -78,10 +62,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc
@warn_unused_result
public func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
return objects.flatMap { try? self.bridgeToSwift.context.existingObjectWithID($0.objectID) }
return self.swiftTransaction.context.fetchExisting(objects) as [NSManagedObject]
}
/**
@@ -91,10 +74,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc
@warn_unused_result
public func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
return objectIDs.flatMap { try? self.bridgeToSwift.context.existingObjectWithID($0) }
return self.swiftTransaction.context.fetchExisting(objectIDs) as [NSManagedObject]
}
/**
@@ -105,14 +87,13 @@ public extension CSBaseDataTransaction {
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
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)
}
/**
@@ -123,14 +104,13 @@ public extension CSBaseDataTransaction {
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
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)
}
/**
@@ -141,14 +121,15 @@ public extension CSBaseDataTransaction {
- returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
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.fetchCount(from, fetchClauses)
return self.swiftTransaction.context
.fetchCount(from, fetchClauses)
.flatMap { NSNumber(value: $0) }
}
/**
@@ -159,14 +140,13 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
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)
}
/**
@@ -180,14 +160,13 @@ public extension CSBaseDataTransaction {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc
@warn_unused_result
public func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
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)
}
/**
@@ -201,13 +180,12 @@ public extension CSBaseDataTransaction {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc
@warn_unused_result
public func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
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
}
/**
@@ -55,9 +55,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
@objc
public func createInto(into: CSInto) -> AnyObject {
public func createInto(_ into: CSInto) -> Any {
return self.bridgeToSwift.create(into.bridgeToSwift)
return self.swiftTransaction.create(into.bridgeToSwift)
}
/**
@@ -67,10 +67,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc
@warn_unused_result
public func editObject(object: NSManagedObject?) -> AnyObject? {
public func editObject(_ object: NSManagedObject?) -> Any? {
return self.bridgeToSwift.edit(object)
return self.swiftTransaction.edit(object)
}
/**
@@ -81,10 +80,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@objc
@warn_unused_result
public func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
return self.swiftTransaction.edit(into.bridgeToSwift, objectID)
}
/**
@@ -93,9 +91,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- parameter object: the `NSManagedObject` to be deleted
*/
@objc
public func deleteObject(object: NSManagedObject?) {
public func deleteObject(_ object: NSManagedObject?) {
self.bridgeToSwift.delete(object)
self.swiftTransaction.delete(object)
}
/**
@@ -104,9 +102,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- parameter objects: the `NSManagedObject`s to be deleted
*/
@objc
public func deleteObjects(objects: [NSManagedObject]) {
public func deleteObjects(_ objects: [NSManagedObject]) {
self.bridgeToSwift.delete(objects)
self.swiftTransaction.delete(objects)
}
/**
@@ -115,24 +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
@warn_unused_result
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.
@@ -140,10 +126,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
*/
@objc
@warn_unused_result
public func insertedObjectsOfType(entity: NSManagedObject.Type) -> Set<NSManagedObject> {
public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.bridgeToSwift.insertedObjects(entity)
return self.swiftTransaction.insertedObjects(entity)
}
/**
@@ -152,10 +137,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s that were inserted to the transaction.
*/
@objc
@warn_unused_result
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.insertedObjectIDs()
return self.swiftTransaction.insertedObjectIDs()
}
/**
@@ -165,22 +149,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/
@objc
@warn_unused_result
public func insertedObjectIDsOfType(entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
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
@warn_unused_result
public func updatedObjects() -> Set<NSManagedObject> {
return self.bridgeToSwift.updatedObjects()
return self.swiftTransaction.insertedObjectIDs(entity)
}
/**
@@ -190,10 +161,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
*/
@objc
@warn_unused_result
public func updatedObjectsOfType(entity: NSManagedObject.Type) -> Set<NSManagedObject> {
public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.bridgeToSwift.updatedObjects(entity)
return self.swiftTransaction.updatedObjects(entity)
}
/**
@@ -202,10 +172,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s that were updated in the transaction.
*/
@objc
@warn_unused_result
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.updatedObjectIDs()
return self.swiftTransaction.updatedObjectIDs()
}
/**
@@ -215,22 +184,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/
@objc
@warn_unused_result
public func updatedObjectIDsOfType(entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
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
@warn_unused_result
public func deletedObjects() -> Set<NSManagedObject> {
return self.bridgeToSwift.deletedObjects()
return self.swiftTransaction.updatedObjectIDs(entity)
}
/**
@@ -240,23 +196,20 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
*/
@objc
@warn_unused_result
public func deletedObjectsOfType(entity: NSManagedObject.Type) -> Set<NSManagedObject> {
public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObject> {
return self.bridgeToSwift.deletedObjects(entity)
return self.swiftTransaction.deletedObjects(entity)
}
/**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- 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
@warn_unused_result
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.deletedObjectIDs()
return self.swiftTransaction.deletedObjectIDs()
}
/**
@@ -266,10 +219,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
@objc
@warn_unused_result
public func deletedObjectIDsOfType(entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set<NSManagedObjectID> {
return self.bridgeToSwift.deletedObjectIDs(entity)
return self.swiftTransaction.deletedObjectIDs(entity)
}
@@ -277,46 +229,50 @@ 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: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSBaseDataTransaction else {
return false
}
return self.bridgeToSwift === object.bridgeToSwift
return self.swiftTransaction === object.swiftTransaction
}
// MARK: CoreStoreObjectiveCType
// MARK: Internal
public typealias SwiftType = BaseDataTransaction
internal let swiftTransaction: BaseDataTransaction
public required init(_ swiftValue: 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
}
// MARK: - BaseDataTransaction
extension BaseDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSBaseDataTransaction
@available(*, deprecated, message: "Use -[deletedObjectsOfType:] and pass the specific entity class")
@objc
public func deletedObjects() -> Set<NSManagedObject> {
return self.swiftTransaction.deletedObjects()
}
}

View File

@@ -38,7 +38,7 @@ import CoreData
public protocol CSFetchClause {
@objc
func applyToFetchRequest(fetchRequest: NSFetchRequest)
func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>)
}
@@ -53,7 +53,7 @@ public protocol CSFetchClause {
public protocol CSQueryClause {
@objc
func applyToFetchRequest(fetchRequest: NSFetchRequest)
func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>)
}
@@ -68,5 +68,5 @@ public protocol CSQueryClause {
public protocol CSDeleteClause {
@objc
func applyToFetchRequest(fetchRequest: NSFetchRequest)
func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>)
}

View File

@@ -44,11 +44,10 @@ public extension CSCoreStore {
}
error: &error];
```
- parameter storage: the `CSInMemoryStore` instance
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously.
*/
public static func addInMemoryStorage(storage: CSInMemoryStore, completion: (CSSetupResult) -> Void) {
public static func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) {
self.defaultStack.addInMemoryStorage(storage, completion: completion)
}
@@ -68,13 +67,12 @@ public extension CSCoreStore {
}
error: &error];
```
- parameter storage: the `CSSQLiteStore` instance
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously. Note that the `CSLocalStorage` associated to the `-[CSSetupResult storage]` may not always be the same instance as the parameter argument if a previous `CSLocalStorage` was already added at the same URL and with the same configuration.
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/
public static func addSQLiteStorage(storage: CSSQLiteStore, completion: (CSSetupResult) -> Void, error: NSErrorPointer) -> NSProgress? {
public static func addSQLiteStorage(_ storage: CSSQLiteStore, completion: @escaping (CSSetupResult) -> Void, error: NSErrorPointer) -> Progress? {
return self.defaultStack.addSQLiteStorage(storage, completion: completion, error: error)
}
@@ -88,7 +86,7 @@ public extension CSCoreStore {
- returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/
@objc
public static func upgradeStorageIfNeeded(storage: CSSQLiteStore, completion: (CSMigrationResult) -> Void, error: NSErrorPointer) -> NSProgress? {
public static func upgradeStorageIfNeeded(_ storage: CSSQLiteStore, completion: @escaping (CSMigrationResult) -> Void, error: NSErrorPointer) -> Progress? {
return self.defaultStack.upgradeStorageIfNeeded(storage, completion: completion, error: error)
}
@@ -101,8 +99,7 @@ public extension CSCoreStore {
- returns: a `CSMigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, `nil` is returned and the `error` argument is set if either inspection of the store failed, or if no mapping model was found/inferred.
*/
@objc
@warn_unused_result
public static func requiredMigrationsForSQLiteStore(storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
public static func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
return self.defaultStack.requiredMigrationsForSQLiteStore(storage, error: error)
}

View File

@@ -27,10 +27,9 @@ import Foundation
import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSCoreStore
@available(OSX 10.12, *)
public extension CSCoreStore {
/**
@@ -40,8 +39,7 @@ public extension CSCoreStore {
- returns: a `CSObjectMonitor` that monitors changes to `object`
*/
@objc
@warn_unused_result
public static func monitorObject(object: NSManagedObject) -> CSObjectMonitor {
public static func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
return self.defaultStack.monitorObject(object)
}
@@ -54,8 +52,7 @@ public extension CSCoreStore {
- returns: a `CSListMonitor` instance that monitors changes to the list
*/
@objc
@warn_unused_result
public static func monitorListFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
public static func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
return self.defaultStack.monitorListFrom(from, fetchClauses: fetchClauses)
}
@@ -68,7 +65,7 @@ public extension CSCoreStore {
- parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/
@objc
public static func monitorListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
public static func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
return self.defaultStack.monitorListByCreatingAsynchronously(
createAsynchronously,
@@ -86,8 +83,7 @@ public extension CSCoreStore {
- returns: a `CSListMonitor` instance that monitors changes to the list
*/
@objc
@warn_unused_result
public static func monitorSectionedListFrom(from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
public static func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
return self.defaultStack.monitorSectionedListFrom(
from,
@@ -105,7 +101,7 @@ public extension CSCoreStore {
- parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/
@objc
public static func monitorSectionedListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
public static func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
self.defaultStack.monitorSectionedListByCreatingAsynchronously(
createAsynchronously,
@@ -115,5 +111,3 @@ public extension CSCoreStore {
)
}
}
#endif

View File

@@ -38,8 +38,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc
@warn_unused_result
public static func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
public static func fetchExistingObject(_ object: NSManagedObject) -> Any? {
return self.defaultStack.fetchExistingObject(object)
}
@@ -51,8 +50,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc
@warn_unused_result
public static func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
public static func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
return self.defaultStack.fetchExistingObjectWithID(objectID)
}
@@ -64,8 +62,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc
@warn_unused_result
public static func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
public static func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
return self.defaultStack.fetchExistingObjects(objects)
}
@@ -77,8 +74,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc
@warn_unused_result
public static func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
public static func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
return self.defaultStack.fetchExistingObjectsWithIDs(objectIDs)
}
@@ -91,8 +87,7 @@ public extension CSCoreStore {
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public static func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
public static func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
return self.defaultStack.fetchOneFrom(from, fetchClauses: fetchClauses)
}
@@ -105,8 +100,7 @@ public extension CSCoreStore {
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public static func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
public static func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
return self.defaultStack.fetchAllFrom(from, fetchClauses: fetchClauses)
}
@@ -119,8 +113,7 @@ public extension CSCoreStore {
- returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public static func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
public static func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
return self.defaultStack.fetchCountFrom(from, fetchClauses: fetchClauses)
}
@@ -133,8 +126,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public static func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
public static func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
return self.defaultStack.fetchObjectIDFrom(from, fetchClauses: fetchClauses)
}
@@ -147,8 +139,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public static func fetchObjectIDsFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
public static func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
return self.defaultStack.fetchObjectIDsFrom(from, fetchClauses: fetchClauses)
}
@@ -164,8 +155,7 @@ public extension CSCoreStore {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc
@warn_unused_result
public static func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
public static func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
return self.defaultStack.queryValueFrom(from, selectClause: selectClause, queryClauses: queryClauses)
}
@@ -181,8 +171,7 @@ public extension CSCoreStore {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc
@warn_unused_result
public static func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
public static func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
return self.defaultStack.queryAttributesFrom(from, selectClause: selectClause, queryClauses: queryClauses)
}

View File

@@ -44,30 +44,18 @@ public extension CSCoreStore {
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
*/
@objc
public static var entityClassesByName: [String: NSManagedObject.Type] {
public static func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return CoreStore.entityTypesByName
}
/**
Returns the entity class for the given entity name from the `defaultStack`'s model.
- parameter name: the entity name
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
*/
@objc
public static func entityClassWithName(name: String) -> NSManagedObject.Type? {
return CoreStore.entityTypesByName[name]
return CoreStore.entityTypesByName(for: type)
}
/**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
*/
@objc
public static func entityDescriptionForClass(type: NSManagedObject.Type) -> NSEntityDescription? {
public static func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? {
return CoreStore.entityDescriptionForType(type)
return CoreStore.entityDescription(for: type)
}
/**
@@ -75,12 +63,12 @@ public extension CSCoreStore {
```
CSSQLiteStore *storage = [CSCoreStore addInMemoryStorageAndWaitAndReturnError:&error];
```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the `defaultStack`
*/
@objc
public static func addInMemoryStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSInMemoryStore? {
@discardableResult
public static func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
return self.defaultStack.addInMemoryStorageAndWaitAndReturnError(error)
}
@@ -90,12 +78,12 @@ public extension CSCoreStore {
```
CSSQLiteStore *storage = [CSCoreStore addSQLiteStorageAndWaitAndReturnError:&error];
```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the `defaultStack`
*/
@objc
public static func addSQLiteStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSSQLiteStore? {
@discardableResult
public static func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
return self.defaultStack.addSQLiteStorageAndWaitAndReturnError(error)
}
@@ -108,13 +96,13 @@ public extension CSCoreStore {
addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
error: &error];
```
- parameter storage: the `CSInMemoryStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the `defaultStack`
*/
@objc
public static func addInMemoryStorageAndWait(storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
@discardableResult
public static func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
return self.defaultStack.addInMemoryStorageAndWait(storage, error: error)
}
@@ -127,14 +115,31 @@ public extension CSCoreStore {
addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
error: &error];
```
- parameter storage: the `CSSQLiteStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the `defaultStack`
*/
@objc
public static func addSQLiteStorageAndWait(storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
@discardableResult
public static func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
return self.defaultStack.addSQLiteStorageAndWait(storage, error: error)
}
}
// MARK: Deprecated
@available(*, deprecated, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public static var entityClassesByName: [EntityName: NSManagedObject.Type] {
return CoreStore.entityTypesByName
}
@available(*, deprecated, message: "Use the new +entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public static func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
return CoreStore.entityTypesByName[name]
}
}

View File

@@ -36,12 +36,9 @@ public extension CSCoreStore {
- 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`.
*/
@objc
public static func beginAsynchronous(closure: (transaction: CSAsynchronousDataTransaction) -> Void) {
public static func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
return CoreStore.beginAsynchronous { (transaction) in
closure(transaction: transaction.bridgeToObjectiveC)
}
self.defaultStack.beginAsynchronous(closure)
}
/**
@@ -51,15 +48,9 @@ public extension CSCoreStore {
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/
@objc
public static func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
return bridge {
CoreStore.beginSynchronous { (transaction) in
closure(transaction: transaction.bridgeToObjectiveC)
}
}
return self.defaultStack.beginSynchronous(closure, error: error)
}
/**
@@ -69,7 +60,6 @@ public extension CSCoreStore {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@objc
@warn_unused_result
public static func beginUnsafe() -> CSUnsafeDataTransaction {
return bridge {
@@ -85,8 +75,7 @@ public extension CSCoreStore {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@objc
@warn_unused_result
public static func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
public static func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
return bridge {
@@ -102,4 +91,15 @@ public extension CSCoreStore {
CoreStore.refreshAndMergeAllObjects()
}
// MARK: Deprecated
@available(*, deprecated, message: "Use the new +[CSCoreStore beginSynchronous:error:] API that reports failure using an error instance.")
@objc
@discardableResult
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return self.defaultStack.beginSynchronous(closure)
}
}

View File

@@ -44,12 +44,11 @@ public extension CSDataStack {
}
error: &error];
```
- parameter storage: the `CSInMemoryStore` instance
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously.
*/
@objc
public func addInMemoryStorage(storage: CSInMemoryStore, completion: (CSSetupResult) -> Void) {
public func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) {
self.bridgeToSwift.addStorage(
storage.bridgeToSwift,
@@ -72,14 +71,13 @@ public extension CSDataStack {
}
error: &error];
```
- parameter storage: the `CSSQLiteStore` instance
- parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously. Note that the `CSLocalStorage` associated to the `-[CSSetupResult storage]` may not always be the same instance as the parameter argument if a previous `CSLocalStorage` was already added at the same URL and with the same configuration.
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/
@objc
public func addSQLiteStorage(storage: CSSQLiteStore, completion: (CSSetupResult) -> Void, error: NSErrorPointer) -> NSProgress? {
public func addSQLiteStorage(_ storage: CSSQLiteStore, completion: @escaping (CSSetupResult) -> Void, error: NSErrorPointer) -> Progress? {
return bridge(error) {
@@ -99,7 +97,7 @@ public extension CSDataStack {
- returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/
@objc
public func upgradeStorageIfNeeded(storage: CSSQLiteStore, completion: (CSMigrationResult) -> Void, error: NSErrorPointer) -> NSProgress? {
public func upgradeStorageIfNeeded(_ storage: CSSQLiteStore, completion: @escaping (CSMigrationResult) -> Void, error: NSErrorPointer) -> Progress? {
return bridge(error) {
@@ -118,12 +116,11 @@ public extension CSDataStack {
- returns: a `CSMigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, `nil` is returned and the `error` argument is set if either inspection of the store failed, or if no mapping model was found/inferred.
*/
@objc
@warn_unused_result
public func requiredMigrationsForSQLiteStore(storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
public func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
return bridge(error) {
try self.bridgeToSwift.requiredMigrationsForStorage(storage.bridgeToSwift)
}
}
}
}

View File

@@ -27,10 +27,9 @@ import Foundation
import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSDataStack
@available(OSX 10.12, *)
public extension CSDataStack {
/**
@@ -40,13 +39,9 @@ public extension CSDataStack {
- returns: a `ObjectMonitor` that monitors changes to `object`
*/
@objc
@warn_unused_result
public func monitorObject(object: NSManagedObject) -> CSObjectMonitor {
public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
return bridge {
self.bridgeToSwift.monitorObject(object)
}
return self.bridgeToSwift.monitorObject(object).bridgeToObjectiveC
}
/**
@@ -57,29 +52,25 @@ public extension CSDataStack {
- returns: a `CSListMonitor` instance that monitors changes to the list
*/
@objc
@warn_unused_result
public func monitorListFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
public func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
)
CoreStore.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires a CSOrderBy clause."
)
return bridge {
ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: nil,
applyFetchClauses: { fetchRequest in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
}
)
}
return ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: nil,
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
}
).bridgeToObjectiveC
}
/**
@@ -90,10 +81,10 @@ public extension CSDataStack {
- parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/
@objc
public func monitorListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
public func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
)
CoreStore.assert(
@@ -104,9 +95,9 @@ public extension CSDataStack {
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: nil,
applyFetchClauses: { fetchRequest in
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
},
createAsynchronously: {
@@ -124,29 +115,25 @@ public extension CSDataStack {
- returns: a `CSListMonitor` instance that monitors changes to the list
*/
@objc
@warn_unused_result
public func monitorSectionedListFrom(from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
public func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
)
CoreStore.assert(
fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause."
)
return bridge {
ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { fetchRequest in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
}
)
}
return ListMonitor(
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
}
).bridgeToObjectiveC
}
/**
@@ -157,10 +144,10 @@ public extension CSDataStack {
- parameter sectionBy: a `CSSectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/
public func monitorSectionedListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
public func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
)
CoreStore.assert(
@@ -171,9 +158,9 @@ public extension CSDataStack {
dataStack: self.bridgeToSwift,
from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { fetchRequest in
applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
},
createAsynchronously: {
@@ -182,5 +169,3 @@ public extension CSDataStack {
)
}
}
#endif

View File

@@ -38,17 +38,9 @@ public extension CSDataStack {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc
@warn_unused_result
public func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
do {
return try self.bridgeToSwift.mainContext.existingObjectWithID(object.objectID)
}
catch _ {
return nil
}
return self.bridgeToSwift.mainContext.fetchExisting(object) as NSManagedObject?
}
/**
@@ -58,17 +50,9 @@ public extension CSDataStack {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@objc
@warn_unused_result
public func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
do {
return try self.bridgeToSwift.mainContext.existingObjectWithID(objectID)
}
catch _ {
return nil
}
return self.bridgeToSwift.mainContext.fetchExisting(objectID) as NSManagedObject?
}
/**
@@ -78,10 +62,9 @@ public extension CSDataStack {
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc
@warn_unused_result
public func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
return objects.flatMap { try? self.bridgeToSwift.mainContext.existingObjectWithID($0.objectID) }
return self.bridgeToSwift.mainContext.fetchExisting(objects) as [NSManagedObject]
}
/**
@@ -91,10 +74,9 @@ public extension CSDataStack {
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
@objc
@warn_unused_result
public func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
return objectIDs.flatMap { try? self.bridgeToSwift.mainContext.existingObjectWithID($0) }
return self.bridgeToSwift.mainContext.fetchExisting(objectIDs) as [NSManagedObject]
}
/**
@@ -105,11 +87,10 @@ public extension CSDataStack {
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.fetchOne(from, fetchClauses)
@@ -123,11 +104,10 @@ public extension CSDataStack {
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.fetchAll(from, fetchClauses)
@@ -141,14 +121,15 @@ public extension CSDataStack {
- returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.fetchCount(from, fetchClauses)
return self.bridgeToSwift.mainContext
.fetchCount(from, fetchClauses)
.flatMap { NSNumber(value: $0) }
}
/**
@@ -159,11 +140,10 @@ public extension CSDataStack {
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.fetchObjectID(from, fetchClauses)
@@ -177,11 +157,10 @@ public extension CSDataStack {
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/
@objc
@warn_unused_result
public func fetchObjectIDsFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
public func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.fetchObjectIDs(from, fetchClauses)
@@ -198,11 +177,10 @@ public extension CSDataStack {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc
@warn_unused_result
public func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.queryValue(from, selectClause, queryClauses)
@@ -219,11 +197,10 @@ public extension CSDataStack {
- returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/
@objc
@warn_unused_result
public func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread."
)
return self.bridgeToSwift.mainContext.queryAttributes(from, selectClause, queryClauses)

View File

@@ -36,28 +36,59 @@ public extension CSDataStack {
- 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`.
*/
@objc
public func beginAsynchronous(closure: (transaction: CSAsynchronousDataTransaction) -> Void) {
public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
return self.bridgeToSwift.beginAsynchronous { (transaction) in
closure(transaction: transaction.bridgeToObjectiveC)
}
self.bridgeToSwift.perform(
asynchronous: { (transaction) in
let csTransaction = transaction.bridgeToObjectiveC
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
CoreStore.log(
.warning,
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
try transaction.cancel()
},
completion: { _ in }
)
}
/**
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
- parameter error: the `CSError` pointer that indicates the reason in case of an failure
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
*/
@objc
public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
return bridge {
return bridge(error) {
self.bridgeToSwift.beginSynchronous { (transaction) in
do {
closure(transaction: transaction.bridgeToObjectiveC)
try self.bridgeToSwift.perform(
synchronous: { (transaction) in
let csTransaction = transaction.bridgeToObjectiveC
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
CoreStore.log(
.warning,
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
}
try transaction.cancel()
}
)
}
catch CoreStoreError.userCancelled {
return
}
}
}
@@ -69,7 +100,6 @@ public extension CSDataStack {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@objc
@warn_unused_result
public func beginUnsafe() -> CSUnsafeDataTransaction {
return bridge {
@@ -85,8 +115,7 @@ public extension CSDataStack {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@objc
@warn_unused_result
public func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
public func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
return bridge {
@@ -102,4 +131,21 @@ public extension CSDataStack {
self.bridgeToSwift.refreshAndMergeAllObjects()
}
// MARK: Deprecated
@available(*, deprecated, message: "Use the new -[CSDataStack beginSynchronous:error:] API that reports failure using an error instance.")
@objc
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return bridge {
self.bridgeToSwift.beginSynchronous { (transaction) in
closure(transaction.bridgeToObjectiveC)
}
}
}
}

View File

@@ -49,75 +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: String?, bundle: NSBundle?, versionChain: [String]?) {
public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init(
DataStack(
modelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? NSBundle.mainBundle(),
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: String?, bundle: NSBundle?, versionTree: [String: String]?) {
self.init(
DataStack(
modelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? NSBundle.mainBundle(),
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter versionChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
- parameter model: the `NSManagedObjectModel` for the stack
- parameter versionTree: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@objc
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
/**
Returns the stack's model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
*/
@@ -128,32 +75,21 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
}
/**
Returns the entity name-to-class type mapping from the stack's model.
Returns the entity name-to-class type mapping from the `CSDataStack`'s model.
*/
@objc
public var entityClassesByName: [String: NSManagedObject.Type] {
public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return self.bridgeToSwift.entityTypesByName
}
/**
Returns the entity class for the given entity name from the stack's's model.
- parameter name: the entity name
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
*/
@objc
public func entityClassWithName(name: String) -> NSManagedObject.Type? {
return self.bridgeToSwift.entityTypesByName[name]
return self.bridgeToSwift.entityTypesByName(for: type)
}
/**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from stack's model.
*/
@objc
public func entityDescriptionForClass(type: NSManagedObject.Type) -> NSEntityDescription? {
public func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? {
return self.bridgeToSwift.entityDescriptionForType(type)
return self.bridgeToSwift.entityDescription(for: type)
}
/**
@@ -161,16 +97,16 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
```
CSSQLiteStore *storage = [dataStack addInMemoryStorageAndWaitAndReturnError:&error];
```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the stack
*/
@objc
public func addInMemoryStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSInMemoryStore? {
@discardableResult
public func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
return bridge(error) {
try self.bridgeToSwift.addStorageAndWait(InMemoryStore)
try self.bridgeToSwift.addStorageAndWait(InMemoryStore())
}
}
@@ -179,16 +115,16 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
```
CSSQLiteStore *storage = [dataStack addSQLiteStorageAndWaitAndReturnError:&error];
```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the stack
*/
@objc
public func addSQLiteStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSSQLiteStore? {
@discardableResult
public func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
return bridge(error) {
try self.bridgeToSwift.addStorageAndWait(SQLiteStore)
try self.bridgeToSwift.addStorageAndWait(SQLiteStore())
}
}
@@ -200,13 +136,13 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
error: &error];
```
- parameter storage: the `CSInMemoryStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the stack
*/
@objc
public func addInMemoryStorageAndWait(storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
@discardableResult
public func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
return bridge(error) {
@@ -222,13 +158,13 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
error: &error];
```
- parameter storage: the `CSSQLiteStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the stack
*/
@objc
public func addSQLiteStorageAndWait(storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
@discardableResult
public func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
return bridge(error) {
@@ -244,7 +180,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
return ObjectIdentifier(self.bridgeToSwift).hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSDataStack else {
@@ -255,7 +191,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -268,6 +204,60 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
self.bridgeToSwift = swiftValue
super.init()
}
// MARK: Deprecated
@available(*, deprecated, message: "Use the -[initWithXcodeModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init(
DataStack(
xcodeModelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionTree:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public var entityClassesByName: [EntityName: NSManagedObject.Type] {
return self.bridgeToSwift.entityTypesByName
}
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
return self.bridgeToSwift.entityTypesByName[name]
}
}
@@ -277,5 +267,8 @@ extension DataStack: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSDataStack
public var bridgeToObjectiveC: CSDataStack {
return CSDataStack(self)
}
}

View File

@@ -0,0 +1,51 @@
//
// CSDynamicSchema.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import CoreData
import Foundation
// MARK: - CSDynamicSchema
/**
The `CSDynamicSchema` serves as the Objective-C bridging type for `DynamicSchema`.
- SeeAlso: `DynamicSchema`
*/
@objc
public protocol CSDynamicSchema {
/**
The version string for this model schema.
*/
@objc
var modelVersion: ModelVersion { get }
/**
Do not call this directly. The `NSManagedObjectModel` for this schema may be created lazily and using this method directly may affect the integrity of the model.
*/
@objc
func rawModel() -> NSManagedObjectModel
}

View File

@@ -53,7 +53,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSError else {
@@ -64,7 +64,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -76,58 +76,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
return swift
}
func createSwiftObject(error: CSError) -> CoreStoreError {
guard error.domain == CoreStoreErrorDomain else {
return .InternalError(NSError: self)
}
guard let code = CoreStoreErrorCode(rawValue: error.code) else {
return .Unknown
}
let info = error.userInfo
switch code {
case .UnknownError:
return .Unknown
case .DifferentPersistentStoreExistsAtURL:
guard case let existingPersistentStoreURL as NSURL = info["existingPersistentStoreURL"] else {
return .Unknown
}
return .DifferentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
case .MappingModelNotFound:
guard let localStoreURL = info["localStoreURL"] as? NSURL,
let targetModel = info["targetModel"] as? NSManagedObjectModel,
let targetModelVersion = info["targetModelVersion"] as? String else {
return .Unknown
}
return .MappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
case .ProgressiveMigrationRequired:
guard let localStoreURL = info["localStoreURL"] as? NSURL else {
return .Unknown
}
return .ProgressiveMigrationRequired(localStoreURL: localStoreURL)
case .InternalError:
guard case let NSError as NSError = info["NSError"] else {
return .Unknown
}
return .InternalError(NSError: NSError)
}
}
let swift = createSwiftObject(self)
let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
self.swiftError = swift
return swift
}
@@ -138,43 +87,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
public init(_ swiftValue: CoreStoreError) {
self.swiftError = swiftValue
let code: CoreStoreErrorCode
let info: [NSObject: AnyObject]
switch swiftValue {
case .Unknown:
code = .UnknownError
info = [:]
case .DifferentStorageExistsAtURL(let existingPersistentStoreURL):
code = .DifferentPersistentStoreExistsAtURL
info = [
"existingPersistentStoreURL": existingPersistentStoreURL
]
case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
code = .MappingModelNotFound
info = [
"localStoreURL": localStoreURL,
"targetModel": targetModel,
"targetModelVersion": targetModelVersion
]
case .ProgressiveMigrationRequired(let localStoreURL):
code = .ProgressiveMigrationRequired
info = [
"localStoreURL": localStoreURL
]
case .InternalError(let NSError):
code = .InternalError
info = [
"NSError": NSError
]
}
super.init(domain: CoreStoreErrorDomain, code: code.rawValue, userInfo: info)
super.init(domain: CoreStoreError.errorDomain, code: swiftValue.errorCode, userInfo: swiftValue.errorUserInfo)
}
public required init?(coder aDecoder: NSCoder) {
@@ -203,33 +116,43 @@ public enum CSErrorCode: Int {
/**
A failure occured because of an unknown error.
*/
case UnknownError
case unknownError
/**
The `NSPersistentStore` could note be initialized because another store existed at the specified `NSURL`.
*/
case DifferentPersistentStoreExistsAtURL
case differentStorageExistsAtURL
/**
An `NSMappingModel` could not be found for a specific source and destination model versions.
*/
case MappingModelNotFound
case mappingModelNotFound
/**
Progressive migrations are disabled for a store, but an `NSMappingModel` could not be found for a specific source and destination model versions.
*/
case ProgressiveMigrationRequired
case progressiveMigrationRequired
/**
An internal SDK call failed with the specified "NSError" userInfo key.
*/
case InternalError
case internalError
/**
The transaction was terminated by a user-thrown error with the specified "Error" userInfo key.
*/
case userError
/**
The transaction was cancelled by the user.
*/
case userCancelled
}
// MARK: - CoreStoreError
extension CoreStoreError: CoreStoreSwiftType {
extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
// MARK: CoreStoreSwiftType
@@ -237,20 +160,106 @@ extension CoreStoreError: CoreStoreSwiftType {
return CSError(self)
}
// MARK: _ObjectiveCBridgeableError
public init?(_bridgedNSError error: NSError) {
guard error.domain == CoreStoreErrorDomain else {
if error is CSError {
self = .internalError(NSError: error)
return
}
return nil
}
guard let code = CoreStoreErrorCode(rawValue: error.code) else {
if error is CSError {
self = .unknown
return
}
return nil
}
let info = error.userInfo
switch code {
case .unknownError:
self = .unknown
case .differentStorageExistsAtURL:
guard case let existingPersistentStoreURL as URL = info["existingPersistentStoreURL"] else {
self = .unknown
return
}
self = .differentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
case .mappingModelNotFound:
guard let localStoreURL = info["localStoreURL"] as? URL,
let targetModel = info["targetModel"] as? NSManagedObjectModel,
let targetModelVersion = info["targetModelVersion"] as? String else {
self = .unknown
return
}
self = .mappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
case .progressiveMigrationRequired:
guard let localStoreURL = info["localStoreURL"] as? URL else {
self = .unknown
return
}
self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
case .internalError:
guard case let nsError as NSError = info["NSError"] else {
self = .unknown
return
}
self = .internalError(NSError: nsError)
case .userError:
guard case let error as Error = info["Error"] else {
self = .unknown
return
}
self = .userError(error: error)
case .userCancelled:
self = .userCancelled
}
}
}
// MARK: Internal
internal extension ErrorType {
internal extension Error {
internal var bridgeToSwift: CoreStoreError {
switch self {
case let error as CoreStoreError: return error
case let error as CSError: return error.bridgeToSwift
default: return .Unknown
case let error as CoreStoreError:
return error
case let error as CSError:
return error.bridgeToSwift
case let error as NSError where type(of: self) is NSError.Type:
return .internalError(NSError: error)
default:
return .unknown
}
}
@@ -258,9 +267,14 @@ internal extension ErrorType {
switch self {
case let error as CoreStoreError: return error.bridgeToObjectiveC
case let error as CSError: return error
default: return self as NSError
case let error as CoreStoreError:
return error.bridgeToObjectiveC
case let error as CSError:
return error
default:
return self as NSError
}
}
}

View File

@@ -35,7 +35,7 @@ import CoreData
- SeeAlso: `From`
*/
@objc
public final class CSFrom: NSObject, CoreStoreObjectiveCType {
public final class CSFrom: NSObject {
/**
The associated `NSManagedObject` entity class
@@ -51,7 +51,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
May contain `NSString` instances to pertain to named configurations, or `NSNull` to pertain to the default configuration
*/
@objc
public var configurations: [AnyObject]? {
public var configurations: [Any]? {
return self.bridgeToSwift.configurations?.map {
@@ -68,11 +68,10 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
```
MyPersonEntity *people = [transaction fetchAllFrom:CSFromClass([MyPersonEntity class])];
```
- parameter entityClass: the `NSManagedObject` class type to be created
*/
@objc
public convenience init(entityClass: AnyClass) {
public convenience init(entityClass: NSManagedObject.Type) {
self.init(From(entityClass))
}
@@ -83,11 +82,11 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
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
public convenience init(entityClass: AnyClass, configuration: AnyObject) {
public convenience init(entityClass: NSManagedObject.Type, configuration: Any) {
switch configuration {
@@ -109,14 +108,13 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
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
public convenience init(entityClass: AnyClass, configurations: [AnyObject]) {
public convenience init(entityClass: NSManagedObject.Type, configurations: [Any]) {
var arguments = [String?]()
var arguments = [ModelConfiguration]()
for configuration in configurations {
switch configuration {
@@ -139,7 +137,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -149,7 +147,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
public init<T: NSManagedObject>(_ swiftValue: From<T>) {
self.bridgeToSwift = swiftValue.upcast()
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -157,7 +155,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
// MARK: - From
extension From: CoreStoreSwiftType {
extension From where T: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -165,4 +163,16 @@ extension From: CoreStoreSwiftType {
return CSFrom(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> From<NSManagedObject> {
return From<NSManagedObject>(
entityClass: self.entityClass,
configurations: self.configurations,
findPersistentStores: self.findPersistentStores
)
}
}

View File

@@ -76,7 +76,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSGroupBy else {
@@ -87,14 +87,14 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CSQueryClause
@objc
public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
public func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
self.bridgeToSwift.applyToFetchRequest(fetchRequest)
}
@@ -118,5 +118,8 @@ extension GroupBy: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSGroupBy
public var bridgeToObjectiveC: CSGroupBy {
return CSGroupBy(self)
}
}

View File

@@ -43,7 +43,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration.
*/
@objc
public convenience init(configuration: String?) {
public convenience init(configuration: ModelConfiguration) {
self.init(InMemoryStore(configuration: configuration))
}
@@ -70,7 +70,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
The configuration name in the model file
*/
@objc
public var configuration: String? {
public var configuration: ModelConfiguration {
return self.bridgeToSwift.configuration
}
@@ -79,7 +79,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
The options dictionary for the `NSPersistentStore`. For `CSInMemoryStore`s, this is always set to `nil`.
*/
@objc
public var storeOptions: [String: AnyObject]? {
public var storeOptions: [AnyHashable: Any]? {
return self.bridgeToSwift.storeOptions
}
@@ -92,7 +92,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
return ObjectIdentifier(self.bridgeToSwift).hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSInMemoryStore else {
@@ -103,7 +103,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -125,5 +125,8 @@ extension InMemoryStore: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSInMemoryStore
public var bridgeToObjectiveC: CSInMemoryStore {
return CSInMemoryStore(self)
}
}

View File

@@ -35,13 +35,13 @@ import CoreData
- SeeAlso: `Into`
*/
@objc
public final class CSInto: NSObject, CoreStoreObjectiveCType {
public final class CSInto: NSObject {
/**
The associated `NSManagedObject` entity class
*/
@objc
public var entityClass: AnyClass {
public var entityClass: NSManagedObject.Type {
return self.bridgeToSwift.entityClass
}
@@ -51,7 +51,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
May contain a `String` to pertain to a named configuration, or `nil` to pertain to the default configuration
*/
@objc
public var configuration: String? {
public var configuration: ModelConfiguration {
return self.bridgeToSwift.configuration
}
@@ -62,11 +62,10 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
MyPersonEntity *person = [transaction createInto:
CSIntoClass([MyPersonEntity class])];
```
- parameter entityClass: the `NSManagedObject` class type to be created
*/
@objc
public convenience init(entityClass: AnyClass) {
public convenience init(entityClass: NSManagedObject.Type) {
self.init(Into(entityClass))
}
@@ -77,12 +76,11 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
MyPersonEntity *person = [transaction createInto:
CSIntoClass([MyPersonEntity class])];
```
- parameter entityClass: the `NSManagedObject` class type to be created
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
*/
@objc
public convenience init(entityClass: AnyClass, configuration: String?) {
public convenience init(entityClass: NSManagedObject.Type, configuration: ModelConfiguration) {
self.init(Into(entityClass, configuration))
}
@@ -95,7 +93,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSInto else {
@@ -106,7 +104,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -116,7 +114,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
public required init<T: NSManagedObject>(_ swiftValue: Into<T>) {
self.bridgeToSwift = swiftValue.upcast()
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -124,7 +122,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
// MARK: - Into
extension Into: CoreStoreSwiftType {
extension Into where T: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -132,4 +130,16 @@ extension Into: CoreStoreSwiftType {
return CSInto(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> Into<NSManagedObject> {
return Into<NSManagedObject>(
entityClass: self.entityClass,
configuration: self.configuration,
inferStoreIfPossible: self.inferStoreIfPossible
)
}
}

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSListMonitor
/**
@@ -36,8 +34,9 @@ import CoreData
- SeeAlso: `ListMonitor`
*/
@available(OSX 10.12, *)
@objc
public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
public final class CSListMonitor: NSObject {
// MARK: Public (Accessors)
@@ -48,7 +47,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified index
*/
@objc
public subscript(index: Int) -> AnyObject {
public subscript(index: Int) -> Any {
return self.bridgeToSwift[index]
}
@@ -60,7 +59,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified index, or `nil` if out of bounds
*/
@objc
public func objectAtSafeIndex(index: Int) -> AnyObject? {
public func objectAtSafeIndex(_ index: Int) -> Any? {
return self.bridgeToSwift[safeIndex: index]
}
@@ -73,12 +72,10 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified section and item index
*/
@objc
public func objectAtSectionIndex(sectionIndex: Int, itemIndex: Int) -> AnyObject {
public func objectAtSectionIndex(_ sectionIndex: Int, itemIndex: Int) -> Any {
return self.bridgeToSwift[sectionIndex, itemIndex]
}
/**
} /**
Returns the object at the given section and item index, or `nil` if out of bounds. This indexer is typically used for `CSListMonitor`s created as sectioned lists.
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will return `nil`.
@@ -86,7 +83,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified section and item index, or `nil` if out of bounds
*/
@objc
public func objectAtSafeSectionIndex(sectionIndex: Int, safeItemIndex itemIndex: Int) -> AnyObject? {
public func objectAtSafeSectionIndex(_ sectionIndex: Int, safeItemIndex itemIndex: Int) -> Any? {
return self.bridgeToSwift[safeSectionIndex: sectionIndex, safeItemIndex: itemIndex]
}
@@ -98,7 +95,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified index path
*/
@objc
public func objectAtIndexPath(indexPath: NSIndexPath) -> AnyObject {
public func objectAtIndexPath(_ indexPath: IndexPath) -> Any {
return self.bridgeToSwift[indexPath]
}
@@ -110,7 +107,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified index path, or `nil` if out of bounds
*/
@objc
public func objectAtSafeIndexPath(indexPath: NSIndexPath) -> AnyObject? {
public func objectAtSafeIndexPath(_ indexPath: IndexPath) -> Any? {
return self.bridgeToSwift[safeIndexPath: indexPath]
}
@@ -121,7 +118,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: `YES` if at least one object in any section exists, `NO` otherwise
*/
@objc
@warn_unused_result
public func hasObjects() -> Bool {
return self.bridgeToSwift.hasObjects()
@@ -134,8 +130,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: `YES` if at least one object in the specified section exists, `NO` otherwise
*/
@objc
@warn_unused_result
public func hasObjectsInSection(section: Int) -> Bool {
public func hasObjectsInSection(_ section: Int) -> Bool {
return self.bridgeToSwift.hasObjectsInSection(section)
}
@@ -146,7 +141,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: all objects in all sections
*/
@objc
@warn_unused_result
public func objectsInAllSections() -> [NSManagedObject] {
return self.bridgeToSwift.objectsInAllSections()
@@ -159,8 +153,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: all objects in the specified section
*/
@objc
@warn_unused_result
public func objectsInSection(section: Int) -> [NSManagedObject] {
public func objectsInSection(_ section: Int) -> [NSManagedObject] {
return self.bridgeToSwift.objectsInSection(section)
}
@@ -172,7 +165,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: all objects in the specified section, or `nil` if out of bounds
*/
@objc
@warn_unused_result
public func objectsInSafeSection(safeSectionIndex section: Int) -> [NSManagedObject]? {
return self.bridgeToSwift.objectsInSection(safeSectionIndex: section)
@@ -184,7 +176,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of sections
*/
@objc
@warn_unused_result
public func numberOfSections() -> Int {
return self.bridgeToSwift.numberOfSections()
@@ -196,7 +187,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of objects in all sections
*/
@objc
@warn_unused_result
public func numberOfObjects() -> Int {
return self.bridgeToSwift.numberOfObjects()
@@ -209,8 +199,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of objects in the specified section
*/
@objc
@warn_unused_result
public func numberOfObjectsInSection(section: Int) -> Int {
public func numberOfObjectsInSection(_ section: Int) -> Int {
return self.bridgeToSwift.numberOfObjectsInSection(section)
}
@@ -222,10 +211,11 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of objects in the specified section, or `nil` if out of bounds
*/
@objc
@warn_unused_result
public func numberOfObjectsInSafeSection(safeSectionIndex section: Int) -> NSNumber? {
return self.bridgeToSwift.numberOfObjectsInSection(safeSectionIndex: section)
return self.bridgeToSwift
.numberOfObjectsInSection(safeSectionIndex: section)
.flatMap { NSNumber(value: $0) }
}
/**
@@ -235,8 +225,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSFetchedResultsSectionInfo` for the specified section
*/
@objc
@warn_unused_result
public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo {
public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo {
return self.bridgeToSwift.sectionInfoAtIndex(section)
}
@@ -248,7 +237,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.
*/
@objc
@warn_unused_result
public func sectionInfoAtSafeSectionIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
return self.bridgeToSwift.sectionInfoAtIndex(safeSectionIndex: section)
@@ -260,7 +248,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSFetchedResultsSectionInfo`s for all sections
*/
@objc
@warn_unused_result
public func sections() -> [NSFetchedResultsSectionInfo] {
return self.bridgeToSwift.sections()
@@ -274,8 +261,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the target section for the specified "Section Index" title and index.
*/
@objc
@warn_unused_result
public func targetSectionForSectionIndexTitle(title title: String, index: Int) -> Int {
public func targetSectionForSectionIndexTitle(title: String, index: Int) -> Int {
return self.bridgeToSwift.targetSectionForSectionIndex(title: title, index: index)
}
@@ -286,7 +272,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the section index titles for all sections
*/
@objc
@warn_unused_result
public func sectionIndexTitles() -> [String] {
return self.bridgeToSwift.sectionIndexTitles()
@@ -299,10 +284,11 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the index of the `NSManagedObject` if it exists in the `CSListMonitor`'s fetched objects, or `nil` if not found.
*/
@objc
@warn_unused_result
public func indexOf(object: NSManagedObject) -> NSNumber? {
public func indexOf(_ object: NSManagedObject) -> NSNumber? {
return self.bridgeToSwift.indexOf(object)
return self.bridgeToSwift
.indexOf(object)
.flatMap { NSNumber(value: $0) }
}
/**
@@ -312,8 +298,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
*/
@objc
@warn_unused_result
public func indexPathOf(object: NSManagedObject) -> NSIndexPath? {
public func indexPathOf(_ object: NSManagedObject) -> IndexPath? {
return self.bridgeToSwift.indexPathOf(object)
}
@@ -333,7 +318,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListObserver` to send change notifications to
*/
@objc
public func addListObserver(observer: CSListObserver) {
public func addListObserver(_ observer: CSListObserver) {
let swift = self.bridgeToSwift
swift.unregisterObserver(observer)
@@ -369,7 +354,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListObjectObserver` to send change notifications to
*/
public func addListObjectObserver(observer: CSListObjectObserver) {
public func addListObjectObserver(_ observer: CSListObjectObserver) {
let swift = self.bridgeToSwift
swift.unregisterObserver(observer)
@@ -425,7 +410,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListSectionObserver` to send change notifications to
*/
@objc
public func addListSectionObserver(observer: CSListSectionObserver) {
public func addListSectionObserver(_ observer: CSListSectionObserver) {
let swift = self.bridgeToSwift
swift.unregisterObserver(observer)
@@ -488,7 +473,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListObserver` to unregister notifications to
*/
@objc
public func removeListObserver(observer: CSListObserver) {
public func removeListObserver(_ observer: CSListObserver) {
self.bridgeToSwift.unregisterObserver(observer)
}
@@ -513,11 +498,11 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Note that only specified clauses will be changed; unspecified clauses will use previous values.
*/
@objc
public func refetch(fetchClauses: [CSFetchClause]) {
public func refetch(_ fetchClauses: [CSFetchClause]) {
self.bridgeToSwift.refetch { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
}
}
@@ -529,7 +514,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSListMonitor else {
@@ -540,7 +525,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -552,7 +537,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
@nonobjc
public required init<T: NSManagedObject>(_ swiftValue: ListMonitor<T>) {
self.bridgeToSwift = swiftValue.upcast()
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -560,7 +545,8 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
// MARK: - ListMonitor
extension ListMonitor: CoreStoreSwiftType {
@available(OSX 10.12, *)
extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -568,6 +554,17 @@ extension ListMonitor: CoreStoreSwiftType {
return CSListMonitor(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> ListMonitor<NSManagedObject> {
@inline(__always)
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
return unsafeBitCast(x, to: type)
}
return noWarnUnsafeBitCast(self, to: ListMonitor<NSManagedObject>.self)
}
}
#endif

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSListObserver
/**
@@ -42,6 +40,7 @@ import CoreData
- SeeAlso: `ListObserver`
*/
@available(OSX 10.12, *)
@objc
public protocol CSListObserver: class, AnyObject {
@@ -51,7 +50,7 @@ public protocol CSListObserver: class, AnyObject {
- parameter monitor: the `CSListMonitor` monitoring the list being observed
*/
@objc
optional func listMonitorWillChange(monitor: CSListMonitor)
optional func listMonitorWillChange(_ monitor: CSListMonitor)
/**
Handles processing right after a change to the observed list occurs
@@ -59,7 +58,7 @@ public protocol CSListObserver: class, AnyObject {
- parameter monitor: the `CSListMonitor` monitoring the object being observed
*/
@objc
optional func listMonitorDidChange(monitor: CSListMonitor)
optional func listMonitorDidChange(_ monitor: CSListMonitor)
/**
This method is broadcast from within the `CSListMonitor`'s `-refetchWithFetchClauses:` method to let observers prepare for the internal `NSFetchedResultsController`'s pending change to its predicate, sort descriptors, etc. Note that the actual refetch will happen after the `NSFetchedResultsController`'s last `-controllerDidChangeContent:` notification completes.
@@ -67,7 +66,7 @@ public protocol CSListObserver: class, AnyObject {
- parameter monitor: the `CSListMonitor` monitoring the object being observed
*/
@objc
optional func listMonitorWillRefetch(monitor: CSListMonitor)
optional func listMonitorWillRefetch(_ monitor: CSListMonitor)
/**
After the `CSListMonitor`'s `-refetchWithFetchClauses:` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `-controllerDidChangeContent:` notification completes.
@@ -75,7 +74,7 @@ public protocol CSListObserver: class, AnyObject {
- parameter monitor: the `CSListMonitor` monitoring the object being observed
*/
@objc
optional func listMonitorDidRefetch(monitor: CSListMonitor)
optional func listMonitorDidRefetch(_ monitor: CSListMonitor)
}
@@ -92,6 +91,7 @@ public protocol CSListObserver: class, AnyObject {
- SeeAlso: `ListObjectObserver`
*/
@available(OSX 10.12, *)
@objc
public protocol CSListObjectObserver: CSListObserver {
@@ -103,7 +103,7 @@ public protocol CSListObjectObserver: CSListObserver {
- parameter indexPath: the new `NSIndexPath` for the inserted object
*/
@objc
optional func listMonitor(monitor: CSListMonitor, didInsertObject object: AnyObject, toIndexPath indexPath: NSIndexPath)
optional func listMonitor(_ monitor: CSListMonitor, didInsertObject object: Any, toIndexPath indexPath: IndexPath)
/**
Notifies that an object was deleted from the specified `NSIndexPath` in the list
@@ -113,7 +113,7 @@ public protocol CSListObjectObserver: CSListObserver {
- parameter indexPath: the `NSIndexPath` for the deleted object
*/
@objc
optional func listMonitor(monitor: CSListMonitor, didDeleteObject object: AnyObject, fromIndexPath indexPath: NSIndexPath)
optional func listMonitor(_ monitor: CSListMonitor, didDeleteObject object: Any, fromIndexPath indexPath: IndexPath)
/**
Notifies that an object at the specified `NSIndexPath` was updated
@@ -123,7 +123,7 @@ public protocol CSListObjectObserver: CSListObserver {
- parameter indexPath: the `NSIndexPath` for the updated object
*/
@objc
optional func listMonitor(monitor: CSListMonitor, didUpdateObject object: AnyObject, atIndexPath indexPath: NSIndexPath)
optional func listMonitor(_ monitor: CSListMonitor, didUpdateObject object: Any, atIndexPath indexPath: IndexPath)
/**
Notifies that an object's index changed
@@ -134,7 +134,7 @@ public protocol CSListObjectObserver: CSListObserver {
- parameter toIndexPath: the new `NSIndexPath` for the moved object
*/
@objc
optional func listMonitor(monitor: CSListMonitor, didMoveObject object: AnyObject, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
optional func listMonitor(_ monitor: CSListMonitor, didMoveObject object: Any, fromIndexPath: IndexPath, toIndexPath: IndexPath)
}
@@ -152,6 +152,7 @@ public protocol CSListObjectObserver: CSListObserver {
- SeeAlso: `ListSectionObserver`
*/
@available(OSX 10.12, *)
@objc
public protocol CSListSectionObserver: CSListObjectObserver {
@@ -163,7 +164,7 @@ public protocol CSListSectionObserver: CSListObjectObserver {
- parameter sectionIndex: the new section index for the new section
*/
@objc
optional func listMonitor(monitor: CSListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
optional func listMonitor(_ monitor: CSListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
/**
Notifies that a section was inserted at the specified index
@@ -173,7 +174,5 @@ public protocol CSListSectionObserver: CSListObjectObserver {
- parameter sectionIndex: the previous section index for the deleted section
*/
@objc
optional func listMonitor(monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
}
#endif

View File

@@ -43,7 +43,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc
public var isSuccess: Bool {
return self.bridgeToSwift.boolValue
return self.bridgeToSwift.isSuccess
}
/**
@@ -52,7 +52,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc
public var isFailure: Bool {
return !self.bridgeToSwift.boolValue
return !self.bridgeToSwift.isSuccess
}
/**
@@ -61,7 +61,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc
public var migrationTypes: [CSMigrationType]? {
guard case .Success(let migrationTypes) = self.bridgeToSwift else {
guard case .success(let migrationTypes) = self.bridgeToSwift else {
return nil
}
@@ -74,7 +74,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc
public var error: NSError? {
guard case .Failure(let error) = self.bridgeToSwift else {
guard case .failure(let error) = self.bridgeToSwift else {
return nil
}
@@ -90,15 +90,15 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
- parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
*/
@objc
public func handleSuccess(@noescape success: (migrationTypes: [CSMigrationType]) -> Void, @noescape failure: (error: NSError) -> Void) {
public func handleSuccess(_ success: (_ migrationTypes: [CSMigrationType]) -> Void, failure: (_ error: NSError) -> Void) {
switch self.bridgeToSwift {
case .Success(let migrationTypes):
success(migrationTypes: migrationTypes.map { $0.bridgeToObjectiveC })
case .success(let migrationTypes):
success(migrationTypes.map { $0.bridgeToObjectiveC })
case .Failure(let error):
failure(error: error.bridgeToObjectiveC)
case .failure(let error):
failure(error.bridgeToObjectiveC)
}
}
@@ -110,13 +110,13 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
- parameter success: the block to execute on success. The block passes an array of `CSMigrationType`s that indicates the migration steps completed.
*/
@objc
public func handleSuccess(@noescape success: (migrationTypes: [CSMigrationType]) -> Void) {
public func handleSuccess(_ success: (_ migrationTypes: [CSMigrationType]) -> Void) {
guard case .Success(let migrationTypes) = self.bridgeToSwift else {
guard case .success(let migrationTypes) = self.bridgeToSwift else {
return
}
success(migrationTypes: migrationTypes.map { $0.bridgeToObjectiveC })
success(migrationTypes.map { $0.bridgeToObjectiveC })
}
/**
@@ -127,13 +127,13 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
- parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
*/
@objc
public func handleFailure(@noescape failure: (error: NSError) -> Void) {
public func handleFailure(_ failure: (_ error: NSError) -> Void) {
guard case .Failure(let error) = self.bridgeToSwift else {
guard case .failure(let error) = self.bridgeToSwift else {
return
}
failure(error: error.bridgeToObjectiveC)
failure(error.bridgeToObjectiveC)
}
@@ -144,7 +144,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSMigrationResult else {
@@ -155,7 +155,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -177,5 +177,8 @@ extension MigrationResult: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSMigrationResult
public var bridgeToObjectiveC: CSMigrationResult {
return CSMigrationResult(self)
}
}

View File

@@ -43,7 +43,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
@objc
public var needsMigration: Bool {
return self.bridgeToSwift.boolValue
return self.bridgeToSwift.hasMigration
}
/**
@@ -90,7 +90,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSMigrationType else {
@@ -101,7 +101,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -123,5 +123,8 @@ extension MigrationType: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSMigrationType
public var bridgeToObjectiveC: CSMigrationType {
return CSMigrationType(self)
}
}

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSObjectMonitor
/**
@@ -36,13 +34,14 @@ import CoreData
- SeeAlso: `ObjectMonitor`
*/
@available(OSX 10.12, *)
@objc
public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
public final class CSObjectMonitor: NSObject {
/**
Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
*/
public var object: AnyObject? {
public var object: Any? {
return self.bridgeToSwift.object
}
@@ -66,7 +65,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: an `CSObjectObserver` to send change notifications to
*/
public func addObjectObserver(observer: CSObjectObserver) {
public func addObjectObserver(_ observer: CSObjectObserver) {
let swift = self.bridgeToSwift
swift.unregisterObserver(observer)
@@ -94,7 +93,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: an `CSObjectObserver` to unregister notifications to
*/
public func removeObjectObserver(observer: CSObjectObserver) {
public func removeObjectObserver(_ observer: CSObjectObserver) {
self.bridgeToSwift.unregisterObserver(observer)
}
@@ -107,7 +106,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSObjectMonitor else {
@@ -118,7 +117,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -130,7 +129,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
@nonobjc
public required init<T: NSManagedObject>(_ swiftValue: ObjectMonitor<T>) {
self.bridgeToSwift = swiftValue.upcast()
self.bridgeToSwift = swiftValue.downcast()
super.init()
}
}
@@ -138,7 +137,8 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
// MARK: - ObjectMonitor
extension ObjectMonitor: CoreStoreSwiftType {
@available(OSX 10.12, *)
extension ObjectMonitor where ObjectMonitor.ObjectType: NSManagedObject {
// MARK: CoreStoreSwiftType
@@ -146,6 +146,17 @@ extension ObjectMonitor: CoreStoreSwiftType {
return CSObjectMonitor(self)
}
// MARK: FilePrivate
fileprivate func downcast() -> ObjectMonitor<NSManagedObject> {
@inline(__always)
func noWarnUnsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
return unsafeBitCast(x, to: type)
}
return noWarnUnsafeBitCast(self, to: ObjectMonitor<NSManagedObject>.self)
}
}
#endif

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSObjectObserver
/**
@@ -40,6 +38,7 @@ import CoreData
- SeeAlso: `ObjectObserver`
*/
@available(OSX 10.12, *)
@objc
public protocol CSObjectObserver: class, AnyObject {
@@ -50,7 +49,7 @@ public protocol CSObjectObserver: class, AnyObject {
- parameter object: the `NSManagedObject` instance being observed
*/
@objc
optional func objectMonitor(monitor: CSObjectMonitor, willUpdateObject object: AnyObject)
optional func objectMonitor(_ monitor: CSObjectMonitor, willUpdateObject object: Any)
/**
Handles processing right after a change to the observed `object` occurs
@@ -60,7 +59,7 @@ public protocol CSObjectObserver: class, AnyObject {
- parameter changedPersistentKeys: an `NSSet` of key paths for the attributes that were changed. Note that `changedPersistentKeys` only contains keys for attributes/relationships present in the persistent store, thus transient properties will not be reported.
*/
@objc
optional func objectMonitor(monitor: CSObjectMonitor, didUpdateObject object: AnyObject, changedPersistentKeys: Set<String>)
optional func objectMonitor(_ monitor: CSObjectMonitor, didUpdateObject object: Any, changedPersistentKeys: Set<String>)
/**
Handles processing right after `object` is deleted
@@ -69,7 +68,5 @@ public protocol CSObjectObserver: class, AnyObject {
- parameter object: the `NSManagedObject` instance being observed
*/
@objc
optional func objectMonitor(monitor: CSObjectMonitor, didDeleteObject object: AnyObject)
optional func objectMonitor(_ monitor: CSObjectMonitor, didDeleteObject object: Any)
}
#endif

View File

@@ -53,7 +53,6 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
fetchAllFrom:CSFromClass([MyPersonEntity class])
fetchClauses:@[CSOrderByKey(CSSortAscending(@"fullname"))]]];
```
- parameter sortDescriptor: a `NSSortDescriptor`
*/
@objc
@@ -69,7 +68,6 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
fetchAllFrom:CSFromClass([MyPersonEntity class])
fetchClauses:@[CSOrderByKeys(CSSortAscending(@"fullname"), CSSortDescending(@"age"), nil))]]];
```
- parameter sortDescriptors: an array of `NSSortDescriptor`s
*/
@objc
@@ -86,7 +84,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
return self.bridgeToSwift.hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSOrderBy else {
@@ -97,14 +95,14 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CSFetchClause, CSQueryClause, CSDeleteClause
@objc
public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
public func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
self.bridgeToSwift.applyToFetchRequest(fetchRequest)
}
@@ -128,5 +126,8 @@ extension OrderBy: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSOrderBy
public var bridgeToObjectiveC: CSOrderBy {
return CSOrderBy(self)
}
}

View File

@@ -40,19 +40,18 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/**
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
*/
@objc
public convenience init(fileURL: NSURL, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: Int) {
public convenience init(fileURL: URL, configuration: ModelConfiguration, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
@@ -61,29 +60,27 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/**
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
*/
@objc
public convenience init(fileName: String, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: Int) {
public convenience init(fileName: String, configuration: ModelConfiguration, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
}
/**
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`.
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
*/
@objc
public convenience override init() {
@@ -98,18 +95,18 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
The `NSURL` that points to the SQLite file
*/
@objc
public var fileURL: NSURL {
public var fileURL: URL {
return self.bridgeToSwift.fileURL
return self.bridgeToSwift.fileURL as URL
}
/**
The `NSBundle`s from which to search mapping models for migrations
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
*/
@objc
public var mappingModelBundles: [NSBundle] {
return self.bridgeToSwift.mappingModelBundles
public var migrationMappingProviders: [Any] {
return self.bridgeToSwift.migrationMappingProviders
}
/**
@@ -133,7 +130,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/**
The configuration name in the model file
*/
public var configuration: String? {
public var configuration: ModelConfiguration {
return self.bridgeToSwift.configuration
}
@@ -145,7 +142,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
```
*/
@objc
public var storeOptions: [String: AnyObject]? {
public var storeOptions: [AnyHashable: Any]? {
return self.bridgeToSwift.storeOptions
}
@@ -154,11 +151,11 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
*/
@objc
public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel, error: NSErrorPointer) -> Bool {
public func cs_eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
return bridge(error) {
try self.bridgeToSwift.eraseStorageAndWait(soureModel: soureModel)
try self.bridgeToSwift.cs_eraseStorageAndWait(metadata: metadata as! [String: Any], soureModelHint: soureModelHint)
}
}
@@ -170,7 +167,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
return ObjectIdentifier(self.bridgeToSwift).hashValue
}
public override func isEqual(object: AnyObject?) -> Bool {
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSSQLiteStore else {
@@ -181,7 +178,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
@@ -194,6 +191,23 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
self.bridgeToSwift = swiftValue
super.init()
}
// MARK: Obsoleted
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileURL:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
fatalError()
}
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileName:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
fatalError()
}
}
@@ -203,5 +217,8 @@ extension SQLiteStore: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSSQLiteStore
public var bridgeToObjectiveC: CSSQLiteStore {
return CSSQLiteStore(self)
}
}

147
Sources/CSSaveResult.swift Normal file
View File

@@ -0,0 +1,147 @@
//
// CSSaveResult.swift
// CoreStore
//
// Copyright © 2016 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: - CSSaveResult
@available(*, deprecated, message: "Use APIs that report failures with `CSError`s instead.")
@objc
public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
@objc
public var isSuccess: Bool {
return self.bridgeToSwift.boolValue
}
@objc
public var isFailure: Bool {
return !self.bridgeToSwift.boolValue
}
@objc
public var hasChanges: Bool {
guard case .success(let hasChanges) = self.bridgeToSwift else {
return false
}
return hasChanges
}
@objc
public var error: NSError? {
guard case .failure(let error) = self.bridgeToSwift else {
return nil
}
return error.bridgeToObjectiveC
}
@objc
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void, failure: (_ error: NSError) -> Void) {
switch self.bridgeToSwift {
case .success(let hasChanges):
success(hasChanges)
case .failure(let error):
failure(error.bridgeToObjectiveC)
}
}
@objc
public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void) {
guard case .success(let hasChanges) = self.bridgeToSwift else {
return
}
success(hasChanges)
}
@objc
public func handleFailure(_ failure: (_ error: NSError) -> Void) {
guard case .failure(let error) = self.bridgeToSwift else {
return
}
failure(error.bridgeToObjectiveC)
}
// MARK: NSObject
public override var hash: Int {
return self.bridgeToSwift.hashValue
}
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSSaveResult else {
return false
}
return self.bridgeToSwift == object.bridgeToSwift
}
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: SaveResult
public required init(_ swiftValue: SaveResult) {
self.bridgeToSwift = swiftValue
super.init()
}
}
// MARK: - SaveResult
@available(*, deprecated, message: "Use the new DataStack.perform(asynchronous:...) and DataStack.perform(synchronous:...) family of APIs")
extension SaveResult: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSSaveResult {
return CSSaveResult(self)
}
}

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