Compare commits

...

187 Commits

Author SHA1 Message Date
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
2f39f9188b WIP: the great renaming 2016-07-21 23:12:24 +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
229 changed files with 23157 additions and 14349 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 language: objective-c
osx_image: xcode7.3 osx_image: xcode8.3
sudo: false sudo: false
git: git:
submodules: false submodules: false
@@ -10,20 +10,22 @@ env:
- LC_CTYPE=en_US.UTF-8 - LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8 - LANG=en_US.UTF-8
matrix: matrix:
- DESTINATION="OS=9.3,name=iPhone 6s" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 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=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator9.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=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator9.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.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator9.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.2,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator9.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.1,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES" - DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="CoreStore iOS7" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES" - 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.11 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 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=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.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=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: before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install cocoapods --no-rdoc --no-ri --no-document --quiet
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.11/Carthage.pkg" - curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.23.0/Carthage.pkg"
- sudo installer -pkg "Carthage.pkg" -target / - sudo installer -pkg "Carthage.pkg" -target /
- rm "Carthage.pkg" - rm "Carthage.pkg"
before_script: 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 Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
fi fi
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "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 "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 "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 Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- if [ $POD_LINT == "YES" ]; then - if [ $POD_LINT == "YES" ]; then
pod lib lint --quick; pod lib lint --quick;
fi fi

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@ class FetchingResultsViewController: UITableViewController {
// MARK: Public // MARK: Public
func setTimeZones(timeZones: [TimeZone]?, title: String) { func set(timeZones: [TimeZone]?, title: String) {
self.timeZones += timeZones ?? [] self.timeZones += timeZones ?? []
self.sectionTitle = title self.sectionTitle = title
@@ -36,14 +36,14 @@ class FetchingResultsViewController: UITableViewController {
// MARK: UITableViewDataSource // MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.timeZones.count 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] let timeZone = self.timeZones[indexPath.row]
cell.textLabel?.text = timeZone.name cell.textLabel?.text = timeZone.name
@@ -55,7 +55,7 @@ class FetchingResultsViewController: UITableViewController {
// MARK: UITableViewDelegate // MARK: UITableViewDelegate
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle return self.sectionTitle
} }

View File

@@ -12,23 +12,23 @@ class QueryingResultsViewController: UITableViewController {
// MARK: Public // MARK: Public
func setValue(value: AnyObject?, title: String) { func set(value: Any?, title: String) {
switch value { switch value {
case (let array as [AnyObject])?: case (let array as [Any])?:
self.values = array.map { (item: AnyObject) -> (title: String, detail: String) in self.values = array.map { (item: Any) -> (title: String, detail: String) in
( (
title: item.description, title: String(describing: item),
detail: String(reflecting: item.dynamicType) detail: String(reflecting: type(of: item))
) )
} }
case let item?: case let item?:
self.values = [ self.values = [
( (
title: item.description, title: String(describing: item),
detail: String(reflecting: item.dynamicType) detail: String(reflecting: type(of: item))
) )
] ]
@@ -55,14 +55,14 @@ class QueryingResultsViewController: UITableViewController {
// MARK: UITableViewDataSource // MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.values.count 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] let value = self.values[indexPath.row]
@@ -75,7 +75,7 @@ class QueryingResultsViewController: UITableViewController {
// MARK: UITableViewDelegate // MARK: UITableViewDelegate
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle return self.sectionTitle
} }

View File

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

View File

@@ -14,17 +14,17 @@ private struct Static {
enum Filter: String { enum Filter: String {
case All = "All Colors" case all = "All Colors"
case Light = "Light Colors" case light = "Light Colors"
case Dark = "Dark Colors" case dark = "Dark Colors"
func next() -> Filter { func next() -> Filter {
switch self { switch self {
case All: return .Light case .all: return .light
case Light: return .Dark case .light: return .dark
case Dark: return .All case .dark: return .all
} }
} }
@@ -32,18 +32,21 @@ private struct Static {
switch self { switch self {
case .All: return Where(true) case .all: return Where(true)
case .Light: return Where("brightness >= 0.9") case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9)
case .Dark: return Where("brightness <= 0.4") case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4)
} }
} }
} }
static var filter = Filter.All { static var filter = Filter.all {
didSet { didSet {
self.palettes.refetch(self.filter.whereClause()) self.palettes.refetch(
self.filter.whereClause(),
OrderBy(.ascending(#keyPath(Palette.hue)))
)
} }
} }
@@ -53,14 +56,14 @@ private struct Static {
SQLiteStore( SQLiteStore(
fileName: "ColorsDemo.sqlite", fileName: "ColorsDemo.sqlite",
configuration: "ObservingDemo", configuration: "ObservingDemo",
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
return CoreStore.monitorSectionedList( return CoreStore.monitorSectionedList(
From(Palette), From<Palette>(),
SectionBy("colorName"), SectionBy(#keyPath(Palette.colorName)),
OrderBy(.Ascending("hue")) OrderBy(.ascending(#keyPath(Palette.hue)))
) )
}() }()
} }
@@ -86,9 +89,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
let navigationItem = self.navigationItem let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [ navigationItem.leftBarButtonItems = [
self.editButtonItem(), self.editButtonItem,
UIBarButtonItem( UIBarButtonItem(
barButtonSystemItem: .Trash, barButtonSystemItem: .trash,
target: self, target: self,
action: #selector(self.resetBarButtonItemTouched(_:)) action: #selector(self.resetBarButtonItemTouched(_:))
) )
@@ -96,13 +99,13 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
let filterBarButton = UIBarButtonItem( let filterBarButton = UIBarButtonItem(
title: Static.filter.rawValue, title: Static.filter.rawValue,
style: .Plain, style: .plain,
target: self, target: self,
action: #selector(self.filterBarButtonItemTouched(_:)) action: #selector(self.filterBarButtonItemTouched(_:))
) )
navigationItem.rightBarButtonItems = [ navigationItem.rightBarButtonItems = [
UIBarButtonItem( UIBarButtonItem(
barButtonSystemItem: .Add, barButtonSystemItem: .add,
target: self, target: self,
action: #selector(self.addBarButtonItemTouched(_:)) action: #selector(self.addBarButtonItemTouched(_:))
), ),
@@ -112,14 +115,14 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
Static.palettes.addObserver(self) Static.palettes.addObserver(self)
self.setTableEnabled(!Static.palettes.isPendingRefetch) self.setTable(enabled: !Static.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): case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as Palette):
destinationViewController.palette = palette destinationViewController.palette = palette
@@ -132,19 +135,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
// MARK: UITableViewDataSource // MARK: UITableViewDataSource
override func numberOfSectionsInTableView(tableView: UITableView) -> Int { override func numberOfSections(in tableView: UITableView) -> Int {
return Static.palettes.numberOfSections() return Static.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 Static.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 = Static.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color cell.colorView?.backgroundColor = palette.color
@@ -156,34 +159,36 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
// MARK: UITableViewDelegate // 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( self.performSegue(
"ObjectObserverDemoViewController", withIdentifier: "ObjectObserverDemoViewController",
sender: Static.palettes[indexPath] sender: Static.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 { switch editingStyle {
case .Delete: case .delete:
let palette = Static.palettes[indexPath] let palette = Static.palettes[indexPath]
CoreStore.beginAsynchronous{ (transaction) -> Void in CoreStore.perform(
asynchronous: { (transaction) in
transaction.delete(palette) transaction.delete(palette)
transaction.commit { (result) -> Void in } },
} completion: { _ in }
)
default: default:
break 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 Static.palettes.sectionInfoAtIndex(section).name
} }
@@ -191,44 +196,44 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
// MARK: ListObserver // MARK: ListObserver
func listMonitorWillChange(monitor: ListMonitor<Palette>) { func listMonitorWillChange(_ monitor: ListMonitor<Palette>) {
self.tableView.beginUpdates() self.tableView.beginUpdates()
} }
func listMonitorDidChange(monitor: ListMonitor<Palette>) { func listMonitorDidChange(_ monitor: ListMonitor<Palette>) {
self.tableView.endUpdates() 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 = Static.filter.rawValue
self.tableView.reloadData() self.tableView.reloadData()
self.setTableEnabled(true) self.setTable(enabled: true)
} }
// MARK: ListObjectObserver // 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 = Static.palettes[indexPath]
cell.colorView?.backgroundColor = palette.color cell.colorView?.backgroundColor = palette.color
@@ -236,23 +241,24 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
} }
} }
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.deleteRows(at: [fromIndexPath], with: .automatic)
self.tableView.insertRowsAtIndexPaths([toIndexPath], withRowAnimation: .Automatic) self.tableView.insertRows(at: [toIndexPath], with: .automatic)
} }
// MARK: ListSectionObserver // 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) {
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic) func listMonitor(_ monitor: ListMonitor<Palette>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .automatic)
} }
@@ -260,43 +266,46 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
private var filterBarButton: UIBarButtonItem? private var filterBarButton: UIBarButtonItem?
@IBAction private dynamic func resetBarButtonItemTouched(sender: AnyObject?) { @IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
CoreStore.beginAsynchronous { (transaction) -> Void in CoreStore.perform(
asynchronous: { (transaction) in
transaction.deleteAll(From(Palette)) transaction.deleteAll(From<Palette>())
transaction.commit() },
} completion: { _ in }
)
} }
@IBAction private dynamic func filterBarButtonItemTouched(sender: AnyObject?) { @IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
Static.filter = Static.filter.next() Static.filter = Static.filter.next()
} }
@IBAction private dynamic func addBarButtonItemTouched(sender: AnyObject?) { @IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
CoreStore.beginAsynchronous { (transaction) -> Void in CoreStore.perform(
asynchronous: { (transaction) in
let palette = transaction.create(Into(Palette)) let palette = transaction.create(Into<Palette>())
palette.setInitialValues() palette.setInitialValues()
},
transaction.commit() completion: { _ in }
} )
} }
private func setTableEnabled(enabled: Bool) { private func setTable(enabled: Bool) {
UIView.animateWithDuration( UIView.animate(
0.2, withDuration: 0.2,
delay: 0, delay: 0,
options: .BeginFromCurrentState, options: .beginFromCurrentState,
animations: { () -> Void in animations: { () -> Void in
if let tableView = self.tableView { if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5 tableView.alpha = enabled ? 1.0 : 0.5
tableView.userInteractionEnabled = enabled tableView.isUserInteractionEnabled = enabled
} }
}, },
completion: nil completion: nil

View File

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

View File

@@ -15,16 +15,16 @@ class ObserversViewController: UIViewController {
// MARK: UIViewController // MARK: UIViewController
override func viewDidAppear(animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
let alert = UIAlertController( let alert = UIAlertController(
title: "Observers Demo", 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\".", 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)) alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
} }
} }

View File

@@ -24,8 +24,8 @@ class Palette: NSManagedObject {
get { get {
let KVCKey = "colorName" let KVCKey = #keyPath(Palette.colorName)
if let colorName = self.accessValueForKVCKey(KVCKey) as? String { if let colorName = self.getValue(forKvcKey: KVCKey) as? String {
return colorName return colorName
} }
@@ -49,7 +49,7 @@ class Palette: NSManagedObject {
} }
set { set {
self.setValue(newValue, forKVCKey: "colorName") self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName))
} }
} }

View File

@@ -8,7 +8,6 @@
import UIKit import UIKit
import CoreStore import CoreStore
import GCDKit
// MARK: - CustomLoggerViewController // MARK: - CustomLoggerViewController
@@ -34,47 +33,47 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
CoreStore.logger = self CoreStore.logger = self
} }
override func viewDidAppear(animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
let alert = UIAlertController( let alert = UIAlertController(
title: "Logger Demo", 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.", 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)) alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
} }
// MARK: CoreStoreLogger // 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 let levelString: String
switch level { switch level {
case .Trace: levelString = "Trace" case .trace: levelString = "Trace"
case .Notice: levelString = "Notice" case .notice: levelString = "Notice"
case .Warning: levelString = "Warning" case .warning: levelString = "Warning"
case .Fatal: levelString = "Fatal" 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() { if condition() {
@@ -82,9 +81,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
} }
let messageString = message() 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 textView: UITextView?
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl? @IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBAction dynamic func segmentedControlValueChanged(sender: AnyObject?) { @IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
switch self.segmentedControl?.selectedSegmentIndex { switch self.segmentedControl?.selectedSegmentIndex {
case 0?: case 0?:
self.dataStack.beginAsynchronous { (transaction) -> Void in let request = NSFetchRequest<NSFetchRequestResult>()
Where(true).applyToFetchRequest(request)
transaction.create(Into(Palette)) Where(false).applyToFetchRequest(request)
}
case 1?: case 1?:
_ = try? dataStack.addStorageAndWait( _ = try? dataStack.addStorageAndWait(
@@ -113,10 +111,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
) )
case 2?: case 2?:
self.dataStack.beginAsynchronous { (transaction) -> Void in DispatchQueue.global(qos: .background).async {
transaction.commit() _ = self.dataStack.fetchOne(From<Palette>())
transaction.commit()
} }
default: default:

View File

@@ -12,7 +12,7 @@ import CoreStore
// MARK: - MigrationsDemoViewController // MARK: - MigrationsDemoViewController
class MigrationsDemoViewController: UIViewController { class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewDataSource, UITableViewDelegate {
// MARK: UIViewController // MARK: UIViewController
@@ -22,28 +22,28 @@ class MigrationsDemoViewController: UIViewController {
if let segmentedControl = self.segmentedControl { if let segmentedControl = self.segmentedControl {
for (index, model) in self.models.enumerate() { for (index, model) in self.models.enumerated() {
segmentedControl.setTitle( segmentedControl.setTitle(
model.label, 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) super.viewDidAppear(animated)
let alert = UIAlertController( let alert = UIAlertController(
title: "Migrations Demo", 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.", 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)) alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) { let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) {
@@ -60,7 +60,7 @@ class MigrationsDemoViewController: UIViewController {
} }
for model in models { for model in models {
if model.version == storeVersion { if model.schemaHistory.currentModelVersion == storeVersion {
return model return model
} }
@@ -72,32 +72,121 @@ class MigrationsDemoViewController: UIViewController {
self.selectModelVersion(modelMetadata) 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 // MARK: Private
private typealias ModelMetadata = (label: String, version: String, entityType: AnyClass, migrationChain: MigrationChain) private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
private let models: [ModelMetadata] = [ private let models: [ModelMetadata] = [
( (
label: "Model V1", label: "Model V1",
version: "MigrationDemo",
entityType: OrganismV1.self, entityType: OrganismV1.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"] migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
), ),
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
)
),
( (
label: "Model V2", label: "Model V2",
version: "MigrationDemoV2",
entityType: OrganismV2.self, entityType: OrganismV2.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: [ migrationChain: [
"MigrationDemo": "MigrationDemoV2", "MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2" "MigrationDemoV3": "MigrationDemoV2"
] ]
), ),
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
)
),
( (
label: "Model V3", label: "Model V3",
version: "MigrationDemoV3",
entityType: OrganismV3.self, entityType: OrganismV3.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"] migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
),
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
) )
] ]
@@ -113,13 +202,13 @@ class MigrationsDemoViewController: UIViewController {
return self._dataStack return self._dataStack
} }
private var _lastSelectedIndexPath: NSIndexPath? private var _lastSelectedIndexPath: IndexPath?
private var lastSelectedIndexPath: NSIndexPath? { private var lastSelectedIndexPath: IndexPath? {
return self._lastSelectedIndexPath return self._lastSelectedIndexPath
} }
private func setSelectedIndexPath(indexPath: NSIndexPath, scrollToSelection: Bool) { private func setSelectedIndexPath(_ indexPath: IndexPath, scrollToSelection: Bool) {
self._lastSelectedIndexPath = indexPath self._lastSelectedIndexPath = indexPath
self.updateDisplay(reloadData: false, scrollToSelection: scrollToSelection, animated: true) 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 progressView: UIProgressView?
@IBOutlet private dynamic weak var tableView: UITableView? @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 { guard let index = self.segmentedControl?.selectedSegmentIndex else {
@@ -142,23 +231,46 @@ class MigrationsDemoViewController: UIViewController {
self.selectModelVersion(self.models[index]) 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 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( let dataStack = DataStack(schemaHistory: model.schemaHistory)
modelName: "MigrationDemo",
migrationChain: model.migrationChain
)
self.setEnabled(false) self.setEnabled(false)
let progress = dataStack.addStorage( let progress = dataStack.addStorage(
SQLiteStore(fileName: "MigrationDemo.sqlite"), SQLiteStore(
fileName: "MigrationDemo.sqlite",
migrationMappingProviders: [
CustomSchemaMappingProvider(
from: "MigrationDemoV3",
to: "MigrationDemoV2",
entityMappings: [
.transformEntity(
sourceEntity: "Organism",
destinationEntity: "Organism",
transformer: { (source, createDestination) in
let destination = createDestination()
destination.enumerateAttributes { (attribute, sourceAttribute) in
if let sourceAttribute = sourceAttribute {
destination[attribute] = source[sourceAttribute]
}
}
destination["numberOfFlippers"] = source["numberOfLimbs"]
}
)
]
)
]
),
completion: { [weak self] (result) -> Void in completion: { [weak self] (result) -> Void in
guard let `self` = self else { guard let `self` = self else {
@@ -166,18 +278,17 @@ class MigrationsDemoViewController: UIViewController {
return return
} }
guard case .Success = result else { guard case .success = result else {
self.setEnabled(true) self.setEnabled(true)
return return
} }
self.setDataStack(dataStack, model: model, scrollToSelection: true) self.set(dataStack: dataStack, model: model, scrollToSelection: true)
let count = dataStack.queryValue( let count = dataStack.queryValue(
From(model.entityType), From(model.entityType),
Select<Int>(.Count("dna")) Select<Int>(.count(#keyPath(OrganismV1.dna))))!
)
if count > 0 { if count > 0 {
self.setEnabled(true) self.setEnabled(true)
@@ -186,7 +297,8 @@ class MigrationsDemoViewController: UIViewController {
for i: Int64 in 0 ..< 20 { for i: Int64 in 0 ..< 20 {
dataStack.beginAsynchronous { (transaction) -> Void in dataStack.perform(
asynchronous: { (transaction) in
for j: Int64 in 0 ..< 500 { for j: Int64 in 0 ..< 500 {
@@ -194,17 +306,17 @@ class MigrationsDemoViewController: UIViewController {
organism.dna = (i * 500) + j + 1 organism.dna = (i * 500) + j + 1
organism.mutate() organism.mutate()
} }
},
transaction.commit() completion: { _ in }
)
} }
} dataStack.perform(
dataStack.beginAsynchronous { [weak self] (transaction) -> Void in asynchronous: { _ in },
completion: { [weak self] _ in
transaction.commit { _ in
self?.setEnabled(true) self?.setEnabled(true)
} }
} )
} }
} }
) )
@@ -218,39 +330,45 @@ class MigrationsDemoViewController: UIViewController {
} }
} }
private func setEnabled(enabled: Bool) { private func setEnabled(_ enabled: Bool) {
UIView.animateWithDuration( UIView.animate(
0.2, withDuration: 0.2,
delay: 0, delay: 0,
options: .BeginFromCurrentState, options: .beginFromCurrentState,
animations: { () -> Void in animations: { () -> Void in
let navigationItem = self.navigationItem let navigationItem = self.navigationItem
navigationItem.leftBarButtonItem?.enabled = enabled navigationItem.leftBarButtonItem?.isEnabled = enabled
navigationItem.rightBarButtonItem?.enabled = enabled navigationItem.rightBarButtonItem?.isEnabled = enabled
navigationItem.hidesBackButton = !enabled navigationItem.hidesBackButton = !enabled
self.segmentedControl?.enabled = enabled self.segmentedControl?.isEnabled = enabled
if let tableView = self.tableView { if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5 tableView.alpha = enabled ? 1.0 : 0.5
tableView.userInteractionEnabled = enabled tableView.isUserInteractionEnabled = enabled
} }
}, },
completion: nil 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 { 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 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) listMonitor.addObserver(self)
self._listMonitor = listMonitor self._listMonitor = listMonitor
@@ -258,7 +376,7 @@ class MigrationsDemoViewController: UIViewController {
if listMonitor.numberOfObjectsInSection(0) > 0 { 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) 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.progressView?.setProgress(Float(progress.fractionCompleted), animated: true)
self.titleLabel?.text = "Migrating: \(progress.localizedDescription)" self.titleLabel?.text = "Migrating: \(progress.localizedDescription ?? "")"
self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription)" 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 lines = [String]()
var organismType = "" var organismType = ""
@@ -287,14 +405,14 @@ class MigrationsDemoViewController: UIViewController {
for property in organism.entity.properties { 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)") lines.append("\(property.name): \(value)")
} }
organismType = organism.entity.managedObjectClassName organismType = organism.entity.managedObjectClassName
} }
self.titleLabel?.text = organismType self.titleLabel?.text = organismType
self.organismLabel?.text = lines.joinWithSeparator("\n") self.organismLabel?.text = lines.joined(separator: "\n")
self.progressView?.progress = 0 self.progressView?.progress = 0
self.headerContainer?.setNeedsLayout() self.headerContainer?.setNeedsLayout()
@@ -311,87 +429,13 @@ class MigrationsDemoViewController: UIViewController {
tableView.layoutIfNeeded() 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, 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

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

View File

@@ -10,14 +10,20 @@ import CoreData
class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy { 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(
dInstance.setValue(sInstance.valueForKey("numberOfFlippers"), forKey: "numberOfLimbs") 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"> <!DOCTYPE database SYSTEM "file:///System/Library/DTDs/CoreData.dtd">
<database> <database>
@@ -10,7 +10,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSPersistenceFrameworkVersion</key> <key>NSPersistenceFrameworkVersion</key>
<integer>526</integer> <integer>754</integer>
<key>NSStoreModelVersionHashes</key> <key>NSStoreModelVersionHashes</key>
<dict> <dict>
<key>XDDevAttributeMapping</key> <key>XDDevAttributeMapping</key>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="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"> <entity name="Organism" representedClassName="CoreStoreDemo.OrganismV1" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" syncable="YES"/> <attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" optional="YES" attributeType="Boolean" syncable="YES"/> <attribute name="hasHead" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" optional="YES" attributeType="Boolean" syncable="YES"/> <attribute name="hasTail" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
</entity> </entity>
<elements> <elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="90"/> <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"?> <?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"> <entity name="Organism" representedClassName="CoreStoreDemo.OrganismV2" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" syncable="YES"/> <attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" syncable="YES"/> <attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" syncable="YES"/> <attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="numberOfFlippers" attributeType="Integer 32" defaultValueString="0" syncable="YES"/> <attribute name="numberOfFlippers" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
</entity> </entity>
<elements> <elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="105"/> <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"?> <?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"> <entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" syncable="YES"/> <attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" attributeType="Boolean" syncable="YES"/> <attribute name="hasHead" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" syncable="YES"/> <attribute name="hasTail" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasVertebrae" attributeType="Boolean" syncable="YES"/> <attribute name="hasVertebrae" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" syncable="YES"/> <attribute name="numberOfLimbs" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" elementID="numberOfFlippers" syncable="YES"/>
</entity> </entity>
<elements> <elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="120"/> <element name="Organism" positionX="-36" positionY="9" width="128" height="120"/>

View File

@@ -22,20 +22,21 @@ private struct Static {
SQLiteStore( SQLiteStore(
fileName: "AccountsDemo_FB_Male.sqlite", fileName: "AccountsDemo_FB_Male.sqlite",
configuration: maleConfiguration, configuration: maleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
try! dataStack.addStorageAndWait( try! dataStack.addStorageAndWait(
SQLiteStore( SQLiteStore(
fileName: "AccountsDemo_FB_Female.sqlite", fileName: "AccountsDemo_FB_Female.sqlite",
configuration: femaleConfiguration, configuration: femaleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
dataStack.beginSynchronous { (transaction) -> Void in _ = try? dataStack.perform(
synchronous: { (transaction) in
transaction.deleteAll(From(UserAccount)) transaction.deleteAll(From<UserAccount>())
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration)) let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Facebook" account1.accountType = "Facebook"
@@ -46,9 +47,8 @@ private struct Static {
account2.accountType = "Facebook" account2.accountType = "Facebook"
account2.name = "Jane Doe HCD" account2.name = "Jane Doe HCD"
account2.friends = 314 account2.friends = 314
transaction.commitAndWait()
} }
)
return dataStack return dataStack
}() }()
@@ -60,20 +60,21 @@ private struct Static {
SQLiteStore( SQLiteStore(
fileName: "AccountsDemo_TW_Male.sqlite", fileName: "AccountsDemo_TW_Male.sqlite",
configuration: maleConfiguration, configuration: maleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
try! dataStack.addStorageAndWait( try! dataStack.addStorageAndWait(
SQLiteStore( SQLiteStore(
fileName: "AccountsDemo_TW_Female.sqlite", fileName: "AccountsDemo_TW_Female.sqlite",
configuration: femaleConfiguration, configuration: femaleConfiguration,
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
dataStack.beginSynchronous { (transaction) -> Void in _ = try? dataStack.perform(
synchronous: { (transaction) in
transaction.deleteAll(From(UserAccount)) transaction.deleteAll(From<UserAccount>())
let account1 = transaction.create(Into<MaleAccount>(maleConfiguration)) let account1 = transaction.create(Into<MaleAccount>(maleConfiguration))
account1.accountType = "Twitter" account1.accountType = "Twitter"
@@ -84,10 +85,8 @@ private struct Static {
account2.accountType = "Twitter" account2.accountType = "Twitter"
account2.name = "#janedoe_hcd" account2.name = "#janedoe_hcd"
account2.friends = 100 account2.friends = 100
transaction.commitAndWait()
} }
)
return dataStack return dataStack
}() }()
} }
@@ -100,53 +99,53 @@ private struct Static {
class StackSetupDemoViewController: UITableViewController { class StackSetupDemoViewController: UITableViewController {
let accounts = [ let accounts = [
Static.facebookStack.fetchAll(From(UserAccount)) ?? [], Static.facebookStack.fetchAll(From(UserAccount.self)) ?? [],
Static.twitterStack.fetchAll(From(UserAccount)) ?? [] Static.twitterStack.fetchAll(From(UserAccount.self)) ?? []
] ]
// MARK: UIViewController // MARK: UIViewController
override func viewWillAppear(animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.tableView.reloadData() self.tableView.reloadData()
let indexPath = NSIndexPath(forRow: 0, inSection: 0) let indexPath = IndexPath(row: 0, section: 0)
self.tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None) self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
self.updateDetailsWithAccount(self.accounts[indexPath.section][indexPath.row]) self.updateDetails(account: self.accounts[indexPath.section][indexPath.row])
} }
override func viewDidAppear(animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
let alert = UIAlertController( let alert = UIAlertController(
title: "Setup Demo", 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.", 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)) alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
} }
// MARK: UITableViewDataSource // MARK: UITableViewDataSource
override func numberOfSectionsInTableView(tableView: UITableView) -> Int { override func numberOfSections(in tableView: UITableView) -> Int {
return self.accounts.count 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 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] let account = self.accounts[indexPath.section][indexPath.row]
cell.textLabel?.text = account.name cell.textLabel?.text = account.name
@@ -158,13 +157,13 @@ class StackSetupDemoViewController: UITableViewController {
// MARK: UITableViewDelegate // 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] 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 { switch section {
@@ -188,7 +187,7 @@ class StackSetupDemoViewController: UITableViewController {
@IBOutlet private dynamic weak var nameLabel: UILabel? @IBOutlet private dynamic weak var nameLabel: UILabel?
@IBOutlet private dynamic weak var friendsLabel: UILabel? @IBOutlet private dynamic weak var friendsLabel: UILabel?
private func updateDetailsWithAccount(account: UserAccount) { private func updateDetails(account: UserAccount) {
self.accountTypeLabel?.text = account.accountType self.accountTypeLabel?.text = account.accountType
self.nameLabel?.text = account.name self.nameLabel?.text = account.name

View File

@@ -11,7 +11,6 @@ import CoreLocation
import MapKit import MapKit
import AddressBookUI import AddressBookUI
import CoreStore import CoreStore
import GCDKit
private struct Static { private struct Static {
@@ -22,21 +21,21 @@ private struct Static {
SQLiteStore( SQLiteStore(
fileName: "PlaceDemo.sqlite", fileName: "PlaceDemo.sqlite",
configuration: "TransactionsDemo", configuration: "TransactionsDemo",
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
var place = CoreStore.fetchOne(From(Place)) var place = CoreStore.fetchOne(From<Place>())
if place == nil { if place == nil {
CoreStore.beginSynchronous { (transaction) -> Void in _ = try? CoreStore.perform(
synchronous: { (transaction) in
let place = transaction.create(Into(Place)) let place = transaction.create(Into<Place>())
place.setInitialValues() place.setInitialValues()
transaction.commitAndWait()
} }
place = CoreStore.fetchOne(From(Place)) )
place = CoreStore.fetchOne(From<Place>())
} }
return CoreStore.monitorObject(place!) return CoreStore.monitorObject(place!)
@@ -71,33 +70,33 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
Static.placeController.addObserver(self) Static.placeController.addObserver(self)
self.navigationItem.rightBarButtonItem = UIBarButtonItem( self.navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .Refresh, barButtonSystemItem: .refresh,
target: self, target: self,
action: #selector(self.refreshButtonTapped(_:)) action: #selector(self.refreshButtonTapped(_:))
) )
} }
override func viewDidAppear(animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
let alert = UIAlertController( let alert = UIAlertController(
title: "Transactions Demo", 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.", 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)) alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
} }
override func viewWillAppear(animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
if let mapView = self.mapView, let place = Static.placeController.object { if let mapView = self.mapView, let place = Static.placeController.object {
mapView.addAnnotation(place) mapView.addAnnotation(place)
mapView.setCenterCoordinate(place.coordinate, animated: false) mapView.setCenter(place.coordinate, animated: false)
mapView.selectAnnotation(place, animated: false) mapView.selectAnnotation(place, animated: false)
} }
} }
@@ -105,14 +104,14 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
// MARK: MKMapViewDelegate // MARK: MKMapViewDelegate
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "MKAnnotationView" let identifier = "MKAnnotationView"
var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil { if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.enabled = true annotationView.isEnabled = true
annotationView.canShowCallout = true annotationView.canShowCallout = true
annotationView.animatesDrop = true annotationView.animatesDrop = true
} }
@@ -127,28 +126,28 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
// MARK: ObjectObserver // MARK: ObjectObserver
func objectMonitor(monitor: ObjectMonitor<Place>, willUpdateObject object: Place) { func objectMonitor(_ monitor: ObjectMonitor<Place>, willUpdateObject object: Place) {
// none // 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 { if let mapView = self.mapView {
mapView.removeAnnotations(mapView.annotations ?? []) mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotation(object) mapView.addAnnotation(object)
mapView.setCenterCoordinate(object.coordinate, animated: true) mapView.setCenter(object.coordinate, animated: true)
mapView.selectAnnotation(object, 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 // none
} }
@@ -160,34 +159,39 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
@IBOutlet weak var mapView: MKMapView? @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( let coordinate = mapView.convert(
gesture.locationInView(mapView), gesture.location(in: mapView),
toCoordinateFromView: mapView toCoordinateFrom: mapView
) )
CoreStore.beginAsynchronous { (transaction) -> Void in CoreStore.perform(
asynchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object) let place = transaction.edit(Static.placeController.object)
place?.coordinate = coordinate place?.coordinate = coordinate
transaction.commit { (_) -> Void in } },
} completion: { _ in }
)
} }
} }
@IBAction dynamic func refreshButtonTapped(sender: AnyObject?) { @IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) {
CoreStore.beginSynchronous { (transaction) -> Void in _ = try? CoreStore.perform(
synchronous: { (transaction) in
let place = transaction.edit(Static.placeController.object) let place = transaction.edit(Static.placeController.object)
place?.setInitialValues() place?.setInitialValues()
transaction.commitAndWait()
} }
)
} }
func geocodePlace(place: Place) { func geocode(place: Place) {
let transaction = CoreStore.beginUnsafe() let transaction = CoreStore.beginUnsafe()

View File

@@ -36,11 +36,12 @@ class BaseTestCase: XCTestCase {
// MARK: Internal // MARK: Internal
@nonobjc @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( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: NSBundle(forClass: self.dynamicType) bundle: Bundle(for: type(of: self))
) )
do { do {
@@ -49,10 +50,10 @@ class BaseTestCase: XCTestCase {
try stack.addStorageAndWait( try stack.addStorageAndWait(
SQLiteStore( SQLiteStore(
fileURL: SQLiteStore.defaultRootDirectory fileURL: SQLiteStore.defaultRootDirectory
.URLByAppendingPathComponent(NSUUID().UUIDString) .appendingPathComponent(UUID().uuidString)
.URLByAppendingPathComponent("\(self.dynamicType)_\(($0 ?? "-null-")).sqlite"), .appendingPathComponent("\(type(of: self))_\(($0 ?? "-null-")).sqlite"),
configuration: $0, configuration: $0,
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
) )
} }
@@ -61,11 +62,11 @@ class BaseTestCase: XCTestCase {
XCTFail(error.coreStoreDumpString) XCTFail(error.coreStoreDumpString)
} }
return closure(dataStack: stack) return closure(stack)
} }
@nonobjc @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)) CoreStore.logger = TestLogger(self.prepareLoggerExpectations(expectations))
defer { defer {
@@ -77,18 +78,18 @@ class BaseTestCase: XCTestCase {
} }
@nonobjc @nonobjc
func expectLogger(expectations: [TestLogger.Expectation: XCTestExpectation]) { func expectLogger(_ expectations: [TestLogger.Expectation: XCTestExpectation]) {
CoreStore.logger = TestLogger(expectations) CoreStore.logger = TestLogger(expectations)
} }
@nonobjc @nonobjc
func prepareLoggerExpectations(expectations: [TestLogger.Expectation]) -> [TestLogger.Expectation: XCTestExpectation] { func prepareLoggerExpectations(_ expectations: [TestLogger.Expectation]) -> [TestLogger.Expectation: XCTestExpectation] {
var testExpectations: [TestLogger.Expectation: XCTestExpectation] = [:] var testExpectations: [TestLogger.Expectation: XCTestExpectation] = [:]
for expectation in expectations { for expectation in expectations {
testExpectations[expectation] = self.expectationWithDescription("Logger Expectation: \(expectation)") testExpectations[expectation] = self.expectation(description: "Logger Expectation: \(expectation)")
} }
return testExpectations return testExpectations
} }
@@ -96,13 +97,13 @@ class BaseTestCase: XCTestCase {
@nonobjc @nonobjc
func checkExpectationsImmediately() { func checkExpectationsImmediately() {
self.waitForExpectationsWithTimeout(0, handler: nil) self.waitForExpectations(timeout: 0, handler: { _ in })
} }
@nonobjc @nonobjc
func waitAndCheckExpectations() { func waitAndCheckExpectations() {
self.waitForExpectationsWithTimeout(10, handler: nil) self.waitForExpectations(timeout: 10, handler: {_ in })
} }
// MARK: XCTestCase // MARK: XCTestCase
@@ -126,7 +127,7 @@ class BaseTestCase: XCTestCase {
private func deleteStores() { 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 { enum Expectation {
case LogWarning case logWarning
case LogFatal case logFatal
case LogError case logError
case AssertionFailure case assertionFailure
case FatalError case fatalError
} }
init(_ expectations: [Expectation: XCTestExpectation]) { init(_ expectations: [Expectation: XCTestExpectation]) {
@@ -152,33 +153,35 @@ class TestLogger: CoreStoreLogger {
// MARK: 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 { switch level {
case .Warning: self.fulfill(.LogWarning) case .warning: self.fulfill(.logWarning)
case .Fatal: self.fulfill(.LogFatal) case .fatal: self.fulfill(.logFatal)
default: break 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() { if condition() {
return 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 var expectations: [Expectation: XCTestExpectation]
private func fulfill(expectation: Expectation) { private func fulfill(_ expectation: Expectation) {
if let instance = self.expectations[expectation] { if let instance = self.expectations[expectation] {

View File

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

View File

@@ -163,7 +163,7 @@
- (void)test_ThatDataStacks_BridgeCorrectly { - (void)test_ThatDataStacks_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc] CSDataStack *dataStack = [[CSDataStack alloc]
initWithModelName:@"Model" initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]] bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]; versionChain:nil];
XCTAssertNotNil(dataStack); XCTAssertNotNil(dataStack);
@@ -197,4 +197,61 @@
XCTAssertNil(sqliteError); 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 @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,211 @@
//
// 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.")
let name = Value.Required<String>(
"name",
customGetter: { (`self`, getValue) in
return "\(self.title.value) \(getValue())"
}
)
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
}
// MARK: - DynamicModelTests
class DynamicModelTests: BaseTestDataTestCase {
func testDynamicModels_CanBeDeclaredCorrectly() {
let dataStack = DataStack(
CoreStoreSchema(
modelVersion: "V1",
entities: [
Entity<Animal>("Animal"),
Entity<Dog>("Dog"),
Entity<Person>("Person")
],
versionLock: [
"Animal": [0x1b59d511019695cf, 0xdeb97e86c5eff179, 0x1cfd80745646cb3, 0x4ff99416175b5b9a],
"Dog": [0xe3f0afeb109b283a, 0x29998d292938eb61, 0x6aab788333cfc2a3, 0x492ff1d295910ea7],
"Person": [0x66d8bbfd8b21561f, 0xcecec69ecae3570f, 0xc4b73d71256214ef, 0x89b99bfe3e013e8b]
]
)
)
self.prepareStack(dataStack, configurations: [nil]) { (stack) in
let k1 = Animal.keyPath({ $0.species })
XCTAssertEqual(k1, "species")
let k2 = Dog.keyPath({ $0.species })
XCTAssertEqual(k2, "species")
let k3 = Dog.keyPath({ $0.nickname })
XCTAssertEqual(k3, "nickname")
let updateDone = self.expectation(description: "update-done")
let fetchDone = self.expectation(description: "fetch-done")
stack.perform(
asynchronous: { (transaction) in
let animal = transaction.create(Into<Animal>())
XCTAssertEqual(animal.species.value, "Swift")
XCTAssertTrue(type(of: animal.species.value) == String.self)
animal.species .= "Sparrow"
XCTAssertEqual(animal.species.value, "Sparrow")
animal.color .= .yellow
XCTAssertEqual(animal.color.value, 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)
person.name .= "John"
XCTAssertEqual(person.name.value, "Mr. John") // Custom getter
person.title .= "Sir"
XCTAssertEqual(person.name.value, "Sir John")
person.pets.value.insert(dog)
XCTAssertEqual(person.pets.count, 1)
XCTAssertEqual(person.pets.value.first, dog)
XCTAssertEqual(person.pets.value.first?.master.value, person)
XCTAssertEqual(dog.master.value, person)
XCTAssertEqual(dog.master.value?.pets.value.first, dog)
},
success: {
updateDone.fulfill()
},
failure: { _ in
XCTFail()
}
)
stack.perform(
asynchronous: { (transaction) in
let p1 = Animal.where({ $0.species == "Sparrow" })
XCTAssertEqual(p1.predicate, NSPredicate(format: "%K == %@", "species", "Sparrow"))
let bird = transaction.fetchOne(From<Animal>(), p1)
XCTAssertNotNil(bird)
XCTAssertEqual(bird!.species.value, "Sparrow")
let p2 = Dog.where({ $0.nickname == "Spot" })
XCTAssertEqual(p2.predicate, NSPredicate(format: "%K == %@", "nickname", "Spot"))
let dog = transaction.fetchOne(From<Dog>(), p2)
XCTAssertNotNil(dog)
XCTAssertEqual(dog!.nickname.value, "Spot")
XCTAssertEqual(dog!.species.value, "Dog")
let person = transaction.fetchOne(From<Person>())
XCTAssertNotNil(person)
XCTAssertEqual(person!.pets.value.first, dog)
let p3 = Dog.where({ $0.age == 10 })
XCTAssertEqual(p3.predicate, NSPredicate(format: "%K == %d", "age", 10))
},
success: {
fetchDone.fulfill()
},
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 @objc
dynamic func test_ThatUnknownErrors_BridgeCorrectly() { dynamic func test_ThatUnknownErrors_BridgeCorrectly() {
let error = CoreStoreError.Unknown let error = CoreStoreError.unknown
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) 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 userInfo: NSDictionary = [:]
let objcError = error.bridgeToObjectiveC let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.UnknownError.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.UnknownError.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
} }
@objc @objc
dynamic func test_ThatDifferentStorageExistsAtURLErrors_BridgeCorrectly() { 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).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue) XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"existingPersistentStoreURL": dummyURL "existingPersistentStoreURL": dummyURL
@@ -70,54 +70,59 @@ final class ErrorTests: XCTestCase {
let objcError = error.bridgeToObjectiveC let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
} }
@objc @objc
dynamic func test_ThatMappingModelNotFoundErrors_BridgeCorrectly() { 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 version = "1.0.0"
let error = CoreStoreError.MappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version) let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: schemaHistory.rawModel, targetModelVersion: version)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.MappingModelNotFound.rawValue) XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"localStoreURL": dummyURL, "localStoreURL": dummyURL,
"targetModel": model, "targetModel": schemaHistory.rawModel,
"targetModelVersion": version "targetModelVersion": version
] ]
let objcError = error.bridgeToObjectiveC let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.MappingModelNotFound.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.MappingModelNotFound.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
} }
@objc @objc
dynamic func test_ThatProgressiveMigrationRequiredErrors_BridgeCorrectly() { 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).domain, CoreStoreErrorDomain)
XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue) XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
let userInfo: NSDictionary = [ let userInfo: NSDictionary = [
"localStoreURL": dummyURL "localStoreURL": dummyURL
@@ -125,14 +130,14 @@ final class ErrorTests: XCTestCase {
let objcError = error.bridgeToObjectiveC let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo) XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
} }
@objc @objc
@@ -144,12 +149,12 @@ final class ErrorTests: XCTestCase {
userInfo: [ userInfo: [
"key1": "value1", "key1": "value1",
"key2": 2, "key2": 2,
"key3": NSDate() "key3": Date()
] ]
) )
let error = CoreStoreError(internalError) let error = CoreStoreError(internalError)
XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) 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 = [ let userInfo: NSDictionary = [
"NSError": internalError "NSError": internalError
@@ -157,13 +162,13 @@ final class ErrorTests: XCTestCase {
let objcError = error.bridgeToObjectiveC let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(error, objcError.bridgeToSwift)
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.InternalError.rawValue) XCTAssertEqual(objcError.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError.userInfo, userInfo) XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(error, objcError2.bridgeToSwift)
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.InternalError.rawValue) XCTAssertEqual(objcError2.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError2.userInfo, userInfo) 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 { do {
let from = From() let from = From<NSManagedObject>()
XCTAssert(from.entityClass === NSManagedObject.self) XCTAssert(from.entityClass === NSManagedObject.self)
XCTAssertNil(from.configurations) XCTAssertNil(from.configurations)
} }
@@ -74,33 +74,33 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) 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"]) XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"])
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
} }
@@ -115,102 +115,102 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config2") let from = From<TestEntity1>("Config2")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>() let from = From<TestEntity2>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config1") let from = From<TestEntity2>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config2") let from = From<TestEntity2>("Config2")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
} }
@@ -225,99 +225,99 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) 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) XCTAssertEqual(Set(affectedConfigurations), ["PF_DEFAULT_CONFIGURATION_NAME", "Config1"] as Set)
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config2") let from = From<TestEntity1>("Config2")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>() let from = From<TestEntity2>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) 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"]) XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"])
} }
do { do {
let from = From<TestEntity2>("Config1") let from = From<TestEntity2>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config2") let from = From<TestEntity2>("Config2")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
} }
@@ -332,96 +332,96 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config2") let from = From<TestEntity1>("Config2")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>() let from = From<TestEntity2>()
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config2"]) XCTAssertEqual(affectedConfigurations, ["Config2"])
} }
do { do {
let from = From<TestEntity2>("Config1") let from = From<TestEntity2>("Config1")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.LogWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config2") let from = From<TestEntity2>("Config2")
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config2"]) XCTAssertEqual(affectedConfigurations, ["Config2"])
} }
} }

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@@ -39,7 +39,7 @@ final class OrderByTests: XCTestCase {
do { do {
let orderBy = OrderBy() let orderBy = OrderBy()
XCTAssertEqual(orderBy, OrderBy([] as [NSSortDescriptor])) XCTAssertEqual(orderBy, OrderBy([NSSortDescriptor]()))
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key", ascending: false))) XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key", ascending: false)))
XCTAssertTrue(orderBy.sortDescriptors.isEmpty) XCTAssertTrue(orderBy.sortDescriptors.isEmpty)
} }
@@ -48,9 +48,9 @@ final class OrderByTests: XCTestCase {
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true) let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
let orderBy = OrderBy(sortDescriptor) let orderBy = OrderBy(sortDescriptor)
XCTAssertEqual(orderBy, OrderBy(sortDescriptor)) XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"))) XCTAssertEqual(orderBy, OrderBy(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key2"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Descending("key1"))) XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key1", ascending: false))) XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key1", ascending: false)))
XCTAssertEqual(orderBy, OrderBy([sortDescriptor])) XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor]) XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
@@ -63,7 +63,7 @@ final class OrderByTests: XCTestCase {
] ]
let orderBy = OrderBy(sortDescriptors) let orderBy = OrderBy(sortDescriptors)
XCTAssertEqual(orderBy, OrderBy(sortDescriptors)) XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual( XCTAssertNotEqual(
orderBy, orderBy,
OrderBy( OrderBy(
@@ -73,30 +73,30 @@ final class OrderByTests: XCTestCase {
] ]
) )
) )
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors) XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
} }
do { do {
let orderBy = OrderBy(.Ascending("key1")) let orderBy = OrderBy(.ascending("key1"))
let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true) let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true)
XCTAssertEqual(orderBy, OrderBy(sortDescriptor)) XCTAssertEqual(orderBy, OrderBy(sortDescriptor))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"))) XCTAssertEqual(orderBy, OrderBy(.ascending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.Descending("key1"))) XCTAssertNotEqual(orderBy, OrderBy(.descending("key1")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key2"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2")))
XCTAssertEqual(orderBy, OrderBy([sortDescriptor])) XCTAssertEqual(orderBy, OrderBy([sortDescriptor]))
XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor]) XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor])
} }
do { do {
let orderBy = OrderBy(.Ascending("key1"), .Descending("key2")) let orderBy = OrderBy(.ascending("key1"), .descending("key2"))
let sortDescriptors = [ let sortDescriptors = [
NSSortDescriptor(key: "key1", ascending: true), NSSortDescriptor(key: "key1", ascending: true),
NSSortDescriptor(key: "key2", ascending: false) NSSortDescriptor(key: "key2", ascending: false)
] ]
XCTAssertEqual(orderBy, OrderBy(sortDescriptors)) XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual( XCTAssertNotEqual(
orderBy, orderBy,
OrderBy( OrderBy(
@@ -106,20 +106,20 @@ final class OrderByTests: XCTestCase {
] ]
) )
) )
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors) XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
} }
do { do {
let sortKeys: [SortKey] = [.Ascending("key1"), .Descending("key2")] let sortKeys: [SortKey] = [.ascending("key1"), .descending("key2")]
let orderBy = OrderBy(sortKeys) let orderBy = OrderBy(sortKeys)
let sortDescriptors = [ let sortDescriptors = [
NSSortDescriptor(key: "key1", ascending: true), NSSortDescriptor(key: "key1", ascending: true),
NSSortDescriptor(key: "key2", ascending: false) NSSortDescriptor(key: "key2", ascending: false)
] ]
XCTAssertEqual(orderBy, OrderBy(sortDescriptors)) XCTAssertEqual(orderBy, OrderBy(sortDescriptors))
XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertNotEqual( XCTAssertNotEqual(
orderBy, orderBy,
OrderBy( OrderBy(
@@ -129,8 +129,8 @@ final class OrderByTests: XCTestCase {
] ]
) )
) )
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2")))
XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3"))) XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3")))
XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors) XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors)
} }
} }
@@ -138,15 +138,15 @@ final class OrderByTests: XCTestCase {
@objc @objc
dynamic func test_ThatOrderByClauseOperations_ComputeCorrectly() { dynamic func test_ThatOrderByClauseOperations_ComputeCorrectly() {
let orderBy1 = OrderBy(.Ascending("key1")) let orderBy1 = OrderBy(.ascending("key1"))
let orderBy2 = OrderBy(.Descending("key2")) let orderBy2 = OrderBy(.descending("key2"))
let orderBy3 = OrderBy(.Ascending("key3")) let orderBy3 = OrderBy(.ascending("key3"))
do { do {
let plusOrderBy = orderBy1 + orderBy2 + orderBy3 let plusOrderBy = orderBy1 + orderBy2 + orderBy3
XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2"), .Ascending("key3"))) XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1")) + OrderBy(.Descending("key2"), .Ascending("key3"))) XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2"), .ascending("key3")))
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2) XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
@@ -158,14 +158,14 @@ final class OrderByTests: XCTestCase {
var plusOrderBy = orderBy1 var plusOrderBy = orderBy1
plusOrderBy += orderBy2 plusOrderBy += orderBy2
XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")))
XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1")) + OrderBy(.Descending("key2"))) XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2")))
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1)
XCTAssertEqual(plusOrderBy.sortDescriptors, orderBy1.sortDescriptors + orderBy2.sortDescriptors) XCTAssertEqual(plusOrderBy.sortDescriptors, orderBy1.sortDescriptors + orderBy2.sortDescriptors)
plusOrderBy += orderBy3 plusOrderBy += orderBy3
XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2"), .Ascending("key3"))) XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3")))
XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2")) + OrderBy(.Ascending("key3"))) XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")) + OrderBy(.ascending("key3")))
XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2) XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3)
XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1)
@@ -178,8 +178,8 @@ final class OrderByTests: XCTestCase {
@objc @objc
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() { dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
let orderBy = OrderBy(.Ascending("key")) let orderBy = OrderBy(.ascending("key"))
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
orderBy.applyToFetchRequest(request) orderBy.applyToFetchRequest(request)
XCTAssertNotNil(request.sortDescriptors) XCTAssertNotNil(request.sortDescriptors)
XCTAssertEqual(request.sortDescriptors ?? [], orderBy.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 import CoreStore
#if os(iOS) || os(watchOS) || os(tvOS)
//MARK: - SectionByTests //MARK: - SectionByTests
@available(OSX 10.12, *)
final class SectionByTests: XCTestCase { final class SectionByTests: XCTestCase {
@objc @objc
@@ -42,16 +41,14 @@ final class SectionByTests: XCTestCase {
let sectionBy = SectionBy("key") let sectionBy = SectionBy("key")
XCTAssertEqual(sectionBy.sectionKeyPath, "key") XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer(sectionName: "key"), "key") XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
} }
do { do {
let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } } let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } }
XCTAssertEqual(sectionBy.sectionKeyPath, "key") XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer(sectionName: "key"), "key:suffix") XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
XCTAssertNil(sectionBy.sectionIndexTransformer(sectionName: nil)) XCTAssertNil(sectionBy.sectionIndexTransformer(nil))
} }
} }
} }
#endif

View File

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

View File

@@ -29,43 +29,51 @@ import CoreStore
// MARK: - SetupTests // MARK: - SetupTests
class SetupTests: BaseTestCase { class SetupTests: BaseTestDataTestCase {
@objc @objc
dynamic func test_ThatDataStacks_ConfigureCorrectly() { dynamic func test_ThatDataStacks_ConfigureCorrectly() {
do { do {
let model = NSManagedObjectModel.mergedModelFromBundles([NSBundle(forClass: self.dynamicType)])! let schemaHistory = SchemaHistory(
XcodeDataModelSchema.from(
let stack = DataStack(model: model, migrationChain: nil) modelName: "Model",
XCTAssertEqual(stack.coordinator.managedObjectModel, model) bundle: Bundle(for: type(of: self))
)
)
let stack = DataStack(schemaHistory: schemaHistory)
XCTAssertEqual(stack.coordinator.managedObjectModel, schemaHistory.rawModel)
XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator) XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator)
XCTAssertNil(stack.rootSavingContext.parentContext) XCTAssertNil(stack.rootSavingContext.parent)
XCTAssertEqual(stack.mainContext.parentContext, stack.rootSavingContext) XCTAssertFalse(stack.rootSavingContext.isDataStackContext)
XCTAssertEqual(stack.model, model) XCTAssertFalse(stack.rootSavingContext.isTransactionContext)
XCTAssertTrue(stack.migrationChain.valid) XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext)
XCTAssertTrue(stack.migrationChain.empty) XCTAssertTrue(stack.mainContext.isDataStackContext)
XCTAssertTrue(stack.migrationChain.rootVersions.isEmpty) XCTAssertFalse(stack.mainContext.isTransactionContext)
XCTAssertTrue(stack.migrationChain.leafVersions.isEmpty) XCTAssertEqual(stack.schemaHistory.rawModel, schemaHistory.rawModel)
XCTAssertTrue(stack.schemaHistory.migrationChain.isValid)
XCTAssertTrue(stack.schemaHistory.migrationChain.isEmpty)
XCTAssertTrue(stack.schemaHistory.migrationChain.rootVersions.isEmpty)
XCTAssertTrue(stack.schemaHistory.migrationChain.leafVersions.isEmpty)
CoreStore.defaultStack = stack CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack) XCTAssertEqual(CoreStore.defaultStack, stack)
} }
do { do {
let migrationChain: MigrationChain = ["version1", "version2", "version3"] let migrationChain: MigrationChain = ["version1", "version2", "version3", "Model"]
let stack = self.expectLogger([.LogWarning]) { let stack = self.expectLogger([.logWarning]) {
DataStack( DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: NSBundle(forClass: self.dynamicType), bundle: Bundle(for: type(of: self)),
migrationChain: migrationChain migrationChain: migrationChain
) )
} }
XCTAssertEqual(stack.modelVersion, "Model") XCTAssertEqual(stack.modelVersion, "Model")
XCTAssertEqual(stack.migrationChain, migrationChain) XCTAssertEqual(stack.schemaHistory.migrationChain, migrationChain)
CoreStore.defaultStack = stack CoreStore.defaultStack = stack
XCTAssertEqual(CoreStore.defaultStack, stack) XCTAssertEqual(CoreStore.defaultStack, stack)
@@ -76,8 +84,8 @@ class SetupTests: BaseTestCase {
dynamic func test_ThatInMemoryStores_SetupCorrectly() { dynamic func test_ThatInMemoryStores_SetupCorrectly() {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: NSBundle(forClass: self.dynamicType) bundle: Bundle(for: type(of: self))
) )
do { do {
@@ -131,8 +139,8 @@ class SetupTests: BaseTestCase {
dynamic func test_ThatSQLiteStores_SetupCorrectly() { dynamic func test_ThatSQLiteStores_SetupCorrectly() {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: NSBundle(forClass: self.dynamicType) bundle: Bundle(for: type(of: self))
) )
do { do {
@@ -154,7 +162,7 @@ class SetupTests: BaseTestCase {
let sqliteStore = SQLiteStore( let sqliteStore = SQLiteStore(
fileName: "ConfigStore1.sqlite", fileName: "ConfigStore1.sqlite",
configuration: "Config1", configuration: "Config1",
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
do { do {
@@ -173,7 +181,7 @@ class SetupTests: BaseTestCase {
let sqliteStore = SQLiteStore( let sqliteStore = SQLiteStore(
fileName: "ConfigStore2.sqlite", fileName: "ConfigStore2.sqlite",
configuration: "Config2", configuration: "Config2",
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
do { 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 @objc
dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() { dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() {
let stack = DataStack( let stack = DataStack(
modelName: "Model", xcodeModelName: "Model",
bundle: NSBundle(forClass: self.dynamicType) bundle: Bundle(for: type(of: self))
) )
do { do {
let sqliteStore = SQLiteStore() let sqliteStore = SQLiteStore.legacy()
do { do {
try stack.addStorageAndWait(sqliteStore) try stack.addStorageAndWait(sqliteStore)
@@ -213,10 +279,10 @@ class SetupTests: BaseTestCase {
} }
do { do {
let sqliteStore = SQLiteStore( let sqliteStore = SQLiteStore.legacy(
fileName: "ConfigStore1.sqlite", fileName: "ConfigStore1.sqlite",
configuration: "Config1", configuration: "Config1",
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
do { do {
@@ -232,10 +298,10 @@ class SetupTests: BaseTestCase {
} }
do { do {
let sqliteStore = SQLiteStore( let sqliteStore = SQLiteStore.legacy(
fileName: "ConfigStore2.sqlite", fileName: "ConfigStore2.sqlite",
configuration: "Config2", configuration: "Config2",
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
do { do {
@@ -250,4 +316,62 @@ class SetupTests: BaseTestCase {
XCTAssert(sqliteStore.matchesPersistentStore(persistentStore!)) 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() { dynamic func test_ThatDefaultInMemoryStores_ConfigureCorrectly() {
let store = InMemoryStore() let store = InMemoryStore()
XCTAssertEqual(store.dynamicType.storeType, NSInMemoryStoreType) XCTAssertEqual(type(of: store).storeType, NSInMemoryStoreType)
XCTAssertNil(store.configuration) XCTAssertNil(store.configuration)
XCTAssertNil(store.storeOptions) XCTAssertNil(store.storeOptions)
} }
@@ -46,7 +46,7 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatCustomInMemoryStores_ConfigureCorrectly() { dynamic func test_ThatCustomInMemoryStores_ConfigureCorrectly() {
let store = InMemoryStore(configuration: "config1") let store = InMemoryStore(configuration: "config1")
XCTAssertEqual(store.dynamicType.storeType, NSInMemoryStoreType) XCTAssertEqual(type(of: store).storeType, NSInMemoryStoreType)
XCTAssertEqual(store.configuration, "config1") XCTAssertEqual(store.configuration, "config1")
XCTAssertNil(store.storeOptions) XCTAssertNil(store.storeOptions)
} }
@@ -55,24 +55,23 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatSQLiteStoreDefaultDirectories_AreCorrect() { dynamic func test_ThatSQLiteStoreDefaultDirectories_AreCorrect() {
#if os(tvOS) #if os(tvOS)
let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
#else #else
let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory
#endif #endif
let defaultSystemDirectory = NSFileManager let defaultSystemDirectory = FileManager.default
.defaultManager() .urls(for: systemDirectorySearchPath, in: .userDomainMask).first!
.URLsForDirectory(systemDirectorySearchPath, inDomains: .UserDomainMask).first!
let defaultRootDirectory = defaultSystemDirectory.URLByAppendingPathComponent( let defaultRootDirectory = defaultSystemDirectory.appendingPathComponent(
NSBundle.mainBundle().bundleIdentifier ?? "com.CoreStore.DataStack", Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack",
isDirectory: true isDirectory: true
) )
let applicationName = (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData" let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData"
let defaultFileURL = defaultRootDirectory let defaultFileURL = defaultRootDirectory
.URLByAppendingPathComponent(applicationName, isDirectory: false) .appendingPathComponent(applicationName, isDirectory: false)
.URLByAppendingPathExtension("sqlite") .appendingPathExtension("sqlite")
XCTAssertEqual(SQLiteStore.defaultRootDirectory, defaultRootDirectory) XCTAssertEqual(SQLiteStore.defaultRootDirectory, defaultRootDirectory)
XCTAssertEqual(SQLiteStore.defaultFileURL, defaultFileURL) XCTAssertEqual(SQLiteStore.defaultFileURL, defaultFileURL)
@@ -82,137 +81,120 @@ final class StorageInterfaceTests: XCTestCase {
dynamic func test_ThatDefaultSQLiteStores_ConfigureCorrectly() { dynamic func test_ThatDefaultSQLiteStores_ConfigureCorrectly() {
let store = SQLiteStore() let store = SQLiteStore()
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertNil(store.configuration) 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.fileURL, SQLiteStore.defaultFileURL)
XCTAssertEqual(store.mappingModelBundles, NSBundle.allBundles()) XCTAssertTrue(store.migrationMappingProviders.isEmpty)
XCTAssertEqual(store.localStorageOptions, [.None]) XCTAssertEqual(store.localStorageOptions, .none)
} }
@objc @objc
dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() { dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() {
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
.URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false) .appendingPathComponent(NSUUID().uuidString, isDirectory: false)!
.URLByAppendingPathExtension("db") .appendingPathExtension("db")
let bundles = [NSBundle(forClass: self.dynamicType)] let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
)
let store = SQLiteStore( let store = SQLiteStore(
fileURL: fileURL, fileURL: fileURL,
configuration: "config1", configuration: "config1",
mappingModelBundles: bundles, migrationMappingProviders: [mappingProvider],
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1") 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.fileURL, fileURL)
XCTAssertEqual(store.mappingModelBundles, bundles) XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
} }
@objc @objc
dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() { dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() {
let fileName = NSUUID().UUIDString + ".db" let fileName = UUID().uuidString + ".db"
let bundles = [NSBundle(forClass: self.dynamicType)] let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
mappingModelBundle: Bundle(for: type(of: self))
)
let store = SQLiteStore( let store = SQLiteStore(
fileName: fileName, fileName: fileName,
configuration: "config1", configuration: "config1",
mappingModelBundles: bundles, migrationMappingProviders: [mappingProvider],
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1") 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.fileURL.lastPathComponent, fileName)
XCTAssertEqual(store.mappingModelBundles, bundles) XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
} }
@objc @objc
dynamic func test_ThatLegacySQLiteStoreDefaultDirectories_AreCorrect() { dynamic func test_ThatLegacySQLiteStoreDefaultDirectories_AreCorrect() {
#if os(tvOS) #if os(tvOS)
let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
#else #else
let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory
#endif #endif
let legacyDefaultRootDirectory = NSFileManager.defaultManager().URLsForDirectory( let legacyDefaultRootDirectory = FileManager.default.urls(
systemDirectorySearchPath, for: systemDirectorySearchPath,
inDomains: .UserDomainMask in: .userDomainMask).first!
).first!
let legacyDefaultFileURL = legacyDefaultRootDirectory let legacyDefaultFileURL = legacyDefaultRootDirectory
.URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false) .appendingPathComponent(DataStack.applicationName, isDirectory: false)
.URLByAppendingPathExtension("sqlite") .appendingPathExtension("sqlite")
XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory) XCTAssertEqual(SQLiteStore.legacyDefaultRootDirectory, legacyDefaultRootDirectory)
XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL) XCTAssertEqual(SQLiteStore.legacyDefaultFileURL, legacyDefaultFileURL)
} }
@objc @objc
dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() { dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() {
let store = LegacySQLiteStore() let store = SQLiteStore.legacy()
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertNil(store.configuration) 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.fileURL, SQLiteStore.legacyDefaultFileURL)
XCTAssertEqual(store.mappingModelBundles, NSBundle.allBundles()) XCTAssertTrue(store.migrationMappingProviders.isEmpty)
XCTAssertEqual(store.localStorageOptions, [.None]) 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])
} }
@objc @objc
dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() { dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() {
let fileName = NSUUID().UUIDString + ".db" let fileName = UUID().uuidString + ".db"
let bundles = [NSBundle(forClass: self.dynamicType)] let mappingProvider = XcodeSchemaMappingProvider(
from: "V1", to: "V2",
let store = LegacySQLiteStore( mappingModelBundle: Bundle(for: type(of: self))
)
let store = SQLiteStore.legacy(
fileName: fileName, fileName: fileName,
configuration: "config1", configuration: "config1",
mappingModelBundles: bundles, migrationMappingProviders: [mappingProvider],
localStorageOptions: .RecreateStoreOnModelMismatch localStorageOptions: .recreateStoreOnModelMismatch
) )
XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1") 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.fileURL.lastPathComponent, fileName)
XCTAssertEqual(store.mappingModelBundles, bundles) XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch])
} }
} }

View File

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

View File

@@ -31,9 +31,9 @@ class TestEntity2: NSManagedObject {
@NSManaged var testEntityID: NSNumber? @NSManaged var testEntityID: NSNumber?
@NSManaged var testString: String? @NSManaged var testString: String?
@NSManaged var testNumber: NSNumber? @NSManaged var testNumber: NSNumber?
@NSManaged var testDate: NSDate? @NSManaged var testDate: Date?
@NSManaged var testBoolean: NSNumber? @NSManaged var testBoolean: NSNumber?
@NSManaged var testDecimal: NSDecimalNumber? @NSManaged var testDecimal: NSDecimalNumber?
@NSManaged var testData: NSData? @NSManaged var testData: Data?
@NSManaged var testNil: String? @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.fetchLimit = 200
$0.predicate = predicate $0.predicate = predicate
} }
let request = NSFetchRequest() let request = CoreStoreFetchRequest()
tweak.applyToFetchRequest(request) tweak.applyToFetchRequest(request)
XCTAssertEqual(request.fetchOffset, 100) XCTAssertEqual(request.fetchOffset, 100)
XCTAssertEqual(request.fetchLimit, 200) XCTAssertEqual(request.fetchLimit, 200)

View File

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

View File

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

941
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,11 +36,11 @@ public extension BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type - parameter into: an `Into` clause specifying the entity type
- parameter source: the object to import values from - 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 - returns: the created `ImportableObject` instance, or `nil` if the import was ignored
*/ */
public func importObject<T where T: NSManagedObject, T: ImportableObject>( public func importObject<T: DynamicObject & ImportableObject>(
into: Into<T>, _ into: Into<T>,
source: T.ImportSource) throws -> T? { source: T.ImportSource) throws -> T? {
CoreStore.assert( CoreStore.assert(
@@ -48,15 +48,16 @@ public extension BaseDataTransaction {
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue." "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 return nil
} }
let object = self.create(into) let object = self.create(into)
try object.didInsertFromImportSource(source, inTransaction: self) try object.didInsert(from: source, in: self)
return object return object
} }
} }
@@ -66,10 +67,10 @@ public extension BaseDataTransaction {
- parameter object: the `NSManagedObject` to update - parameter object: the `NSManagedObject` to update
- parameter source: the object to import values from - 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>( public func importObject<T: DynamicObject & ImportableObject>(
object: T, _ object: T,
source: T.ImportSource) throws { source: T.ImportSource) throws {
CoreStore.assert( 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." "Attempted to import an object of type \(cs_typeName(object)) outside the transaction's designated queue."
) )
try cs_autoreleasepool { try autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else { let entityType = type(of: object)
guard entityType.shouldInsert(from: source, in: self) else {
return return
} }
try object.didInsert(from: source, in: self)
try object.didInsertFromImportSource(source, inTransaction: self)
} }
} }
@@ -93,31 +94,31 @@ public extension BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type - parameter into: an `Into` clause specifying the entity type
- parameter sourceArray: the array of objects to import values from - parameter sourceArray: the array of objects to import values from
- 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 - returns: the array of created `ImportableObject` instances
*/ */
public func importObjects<T, S: SequenceType where T: NSManagedObject, T: ImportableObject, S.Generator.Element == T.ImportSource>( public func importObjects<T: DynamicObject & ImportableObject, S: Sequence>(
into: Into<T>, _ into: Into<T>,
sourceArray: S) throws -> [T] { sourceArray: S) throws -> [T] where S.Iterator.Element == T.ImportSource {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue." "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
) )
return try cs_autoreleasepool { return try autoreleasepool {
return try sourceArray.flatMap { (source) -> T? in 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 nil
} }
return try autoreleasepool {
return try cs_autoreleasepool {
let object = self.create(into) let object = self.create(into)
try object.didInsertFromImportSource(source, inTransaction: self) try object.didInsert(from: source, in: self)
return object return object
} }
} }
@@ -129,11 +130,11 @@ public extension BaseDataTransaction {
- parameter into: an `Into` clause specifying the entity type - parameter into: an `Into` clause specifying the entity type
- parameter source: the object to import values from - 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 - returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
*/ */
public func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>( public func importUniqueObject<T: DynamicObject & ImportableUniqueObject>(
into: Into<T>, _ into: Into<T>,
source: T.ImportSource) throws -> T? { source: T.ImportSource) throws -> T? {
CoreStore.assert( CoreStore.assert(
@@ -141,34 +142,33 @@ public extension BaseDataTransaction {
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue." "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
) )
return try cs_autoreleasepool { return try autoreleasepool {
let uniqueIDKeyPath = T.uniqueIDKeyPath let entityType = into.entityClass
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else { let uniqueIDKeyPath = entityType.uniqueIDKeyPath
guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
return nil 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 return nil
} }
try object.update(from: source, in: self)
try object.updateFromImportSource(source, inTransaction: self)
return object return object
} }
else { else {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else { guard entityType.shouldInsert(from: source, in: self) else {
return nil return nil
} }
let object = self.create(into) let object = self.create(into)
object.uniqueIDValue = uniqueIDValue object.uniqueIDValue = uniqueIDValue
try object.didInsertFromImportSource(source, inTransaction: self) try object.didInsert(from: source, in: self)
return object 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. 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 into: an `Into` clause specifying the entity type
- parameter sourceArray: the array of objects to import values from - parameter sourceArray: the array of objects to import values from
- 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. - 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 - returns: the array of created/updated `ImportableUniqueObject` instances
*/ */
public func importUniqueObjects<T, S: SequenceType where T: NSManagedObject, T: ImportableUniqueObject, S.Generator.Element == T.ImportSource>( public func importUniqueObjects<T: DynamicObject & ImportableUniqueObject, S: Sequence>(
into: Into<T>, _ into: Into<T>,
sourceArray: S, 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( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue." "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
) )
return try cs_autoreleasepool { return try autoreleasepool {
var mapping = Dictionary<T.UniqueIDType, T.ImportSource>() let entityType = into.entityClass
let sortedIDs = try cs_autoreleasepool { var importSourceByID = Dictionary<T.UniqueIDType, T.ImportSource>()
let sortedIDs = try autoreleasepool {
return try sourceArray.flatMap { (source) -> T.UniqueIDType? in 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 return nil
} }
importSourceByID[uniqueIDValue] = source // effectively replaces duplicate with the latest
mapping[uniqueIDValue] = source
return uniqueIDValue return uniqueIDValue
} }
} }
mapping = try cs_autoreleasepool { try preProcess(mapping: mapping) } importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
var objects = Dictionary<T.UniqueIDType, T>() var existingObjectsByID = Dictionary<T.UniqueIDType, T>()
for object in self.fetchAll(From(T), Where(T.uniqueIDKeyPath, isMemberOf: sortedIDs)) ?? [] { self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
.forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
try cs_autoreleasepool { var processedObjectIDs = Set<T.UniqueIDType>()
var result = [T]()
let uniqueIDValue = object.uniqueIDValue for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
guard let source = mapping.removeValueForKey(uniqueIDValue) guard let source = importSourceByID[objectID] else {
where T.shouldUpdateFromImportSource(source, inTransaction: self) else {
continue
}
try autoreleasepool {
if let object = existingObjectsByID[objectID] {
guard entityType.shouldUpdate(from: source, in: self) else {
return return
} }
try object.update(from: source, in: self)
try object.updateFromImportSource(source, inTransaction: self) result.append(object)
objects[uniqueIDValue] = object
}
}
for (uniqueIDValue, source) in mapping {
try cs_autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
return
} }
else if entityType.shouldInsert(from: source, in: self) {
let object = self.create(into) let object = self.create(into)
object.uniqueIDValue = uniqueIDValue object.uniqueIDValue = objectID
try object.didInsertFromImportSource(source, inTransaction: self) try object.didInsert(from: source, in: self)
result.append(object)
objects[uniqueIDValue] = object }
processedObjectIDs.insert(objectID)
} }
} }
return result
return sortedIDs.flatMap { objects[$0] }
} }
} }
} }

View File

@@ -29,92 +29,99 @@ import CoreData
// MARK: - DataTransaction // 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 - 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: DynamicObject>(_ object: T) -> T? {
public func fetchExisting<T: NSManagedObject>(object: T) -> T? {
do { return self.context.fetchExisting(object)
return (try self.context.existingObjectWithID(object.objectID) as! T)
}
catch _ {
return nil
}
} }
/** /**
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 - 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: DynamicObject>(_ objectID: NSManagedObjectID) -> T? {
public func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
do { return self.context.fetchExisting(objectID)
return (try self.context.existingObjectWithID(objectID) as! T)
}
catch _ {
return nil
}
} }
/** /**
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 - parameter objects: an array of `DynamicObject`s created/fetched outside the transaction
- 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: DynamicObject, S: Sequence>(_ objects: S) -> [T] where S.Iterator.Element == T {
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == T>(objects: S) -> [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 - 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: DynamicObject, S: Sequence>(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == NSManagedObjectID>(objectIDs: S) -> [T] {
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 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. - 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: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> T? {
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? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), 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 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. - 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 fetchOne<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
public func fetchAll<T: NSManagedObject>(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 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. - 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: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), 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 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. - 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 fetchAll<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
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? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue." "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
) )
return self.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) 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 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. - 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 fetchCount<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
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 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. - 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: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), 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 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. - 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 fetchObjectID<T: DynamicObject>(_ from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
public func fetchObjectIDs<T: NSManagedObject>(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 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. - 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: DynamicObject>(_ from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), 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 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. - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number of `NSManagedObject`s deleted - 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( CoreStore.assert(
self.isRunningInAllowedQueue(), 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.fetchObjectIDs(from, fetchClauses)
return self.context.deleteAll(from, deleteClauses)
} }
/**
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 // MARK: QueryableSource
- 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)
}
/** /**
Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. 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. - 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. - 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: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue." "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
) )
return self.context.queryValue(from, selectClause, queryClauses) 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. - 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. - 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: DynamicObject, U: QueryableAttributeType>(_ from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue." "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
) )
return self.context.queryValue(from, selectClause, queryClauses) 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. - 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. - 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: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[String: Any]]? {
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue." "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
) )
return self.context.queryAttributes(from, selectClause, queryClauses) 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. - 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. - 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: DynamicObject>(_ from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to query from a \(cs_typeName(self)) outside its designated queue." "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
) )
return self.context.queryAttributes(from, selectClause, queryClauses) 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 Foundation
import CoreData import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - BaseDataTransaction // 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 - parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type. - returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type.
*/ */
public func create<T: NSManagedObject>(into: Into<T>) -> T { public func create<T: DynamicObject>(_ into: Into<T>) -> T {
let entityClass = into.entityClass
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), 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 context = self.context
let entityClass = (into.entityClass as! NSManagedObject.Type) let dataStack = context.parentStack!
let entityIdentifier = EntityIdentifier(entityClass)
if into.inferStoreIfPossible { if into.inferStoreIfPossible {
switch context.parentStack!.persistentStoreForEntityClass( switch dataStack.persistentStore(
entityClass, for: entityIdentifier,
configuration: nil, configuration: nil,
inferStoreIfPossible: true inferStoreIfPossible: true
) { ) {
case (let persistentStore?, _): case (let persistentStore?, _):
let object = entityClass.createInContext(context) as! T return entityClass.cs_forceCreate(
context.assignObject(object, toPersistentStore: persistentStore) entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
return object into: context,
assignTo: persistentStore
)
case (nil, true): case (nil, true):
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.") CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
@@ -84,17 +85,19 @@ public /*abstract*/ class BaseDataTransaction {
} }
else { else {
switch context.parentStack!.persistentStoreForEntityClass( switch dataStack.persistentStore(
entityClass, for: entityIdentifier,
configuration: into.configuration configuration: into.configuration
?? into.dynamicType.defaultConfigurationName, ?? DataStack.defaultConfigurationName,
inferStoreIfPossible: false inferStoreIfPossible: false
) { ) {
case (let persistentStore?, _): case (let persistentStore?, _):
let object = entityClass.createInContext(context) as! T return entityClass.cs_forceCreate(
context.assignObject(object, toPersistentStore: persistentStore) entityDescription: dataStack.entityDescription(for: entityIdentifier)!,
return object into: context,
assignTo: persistentStore
)
case (nil, true): case (nil, true):
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.") CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
@@ -118,8 +121,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited - parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
@warn_unused_result public func edit<T: DynamicObject>(_ object: T?) -> T? {
public func edit<T: NSManagedObject>(object: T?) -> T? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
@@ -139,19 +141,18 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited - parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
@warn_unused_result public func edit<T: DynamicObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), 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( CoreStore.assert(
into.inferStoreIfPossible into.inferStoreIfPossible
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName, || (into.configuration ?? DataStack.defaultConfigurationName) == objectID.persistentStore?.configurationName,
"Attempted to update an entity of type \(cs_typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`." "Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
) )
return self.fetchExisting(objectID) as? T return self.fetchExisting(objectID)
} }
/** /**
@@ -159,17 +160,16 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` to be deleted - parameter object: the `NSManagedObject` to be deleted
*/ */
public func delete(object: NSManagedObject?) { public func delete<T: DynamicObject>(_ object: T?) {
CoreStore.assert( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to delete an entity outside its designated queue." "Attempted to delete an entity outside its designated queue."
) )
guard let object = object else { let context = self.context
object
return .flatMap(context.fetchExisting)
} .flatMap({ context.delete($0.cs_toRaw()) })
self.context.fetchExisting(object)?.deleteFromContext()
} }
/** /**
@@ -179,7 +179,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object2: another `NSManagedObject` to be deleted - parameter object2: another `NSManagedObject` to be deleted
- parameter objects: other `NSManagedObject`s 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 }) self.delete(([object1, object2] + objects).flatMap { $0 })
} }
@@ -189,15 +189,14 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objects: the `NSManagedObject`s to be deleted - 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( CoreStore.assert(
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to delete entities outside their designated queue." "Attempted to delete entities outside their designated queue."
) )
let context = self.context let context = self.context
objects.forEach { context.fetchExisting($0)?.deleteFromContext() } objects.forEach { context.fetchExisting($0).flatMap({ context.delete($0.cs_toRaw()) }) }
} }
/** /**
@@ -209,7 +208,6 @@ public /*abstract*/ class BaseDataTransaction {
self.isRunningInAllowedQueue(), self.isRunningInAllowedQueue(),
"Attempted to refresh entities outside their designated queue." "Attempted to refresh entities outside their designated queue."
) )
self.context.refreshAndMergeAllObjects() self.context.refreshAndMergeAllObjects()
} }
@@ -217,44 +215,22 @@ public /*abstract*/ class BaseDataTransaction {
// MARK: Inspecting Pending Objects // MARK: Inspecting Pending Objects
/** /**
Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `commit()` method was called. Returns all pending `DynamicObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- returns: a `Set` of pending `NSManagedObject`s that were inserted to the transaction. - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were inserted to the transaction.
*/ */
@warn_unused_result public func insertedObjects<T: DynamicObject>(_ entity: T.Type) -> Set<T> {
public func insertedObjects() -> Set<NSManagedObject> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue." "Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access inserted objects from an already committed \(cs_typeName(self))." "Attempted to access inserted objects from an already committed \(cs_typeName(self))."
) )
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
return self.context.insertedObjects
}
/**
Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
*/
@warn_unused_result
public func insertedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
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 Set(self.context.insertedObjects.flatMap { $0 as? T })
} }
/** /**
@@ -262,81 +238,55 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObjectID`s that were inserted to the transaction. - returns: a `Set` of pending `NSManagedObjectID`s that were inserted to the transaction.
*/ */
@warn_unused_result
public func insertedObjectIDs() -> Set<NSManagedObjectID> { public func insertedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue." "Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))." "Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
) )
return Set(self.context.insertedObjects.map { $0.objectID }) return Set(self.context.insertedObjects.map { $0.objectID })
} }
/** /**
Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called. Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/ */
@warn_unused_result public func insertedObjectIDs<T: DynamicObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
public func insertedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue." "Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))." "Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
) )
return Set(self.context.insertedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
return Set(self.context.insertedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
} }
/** /**
Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `commit()` method was called. Returns all pending `DynamicObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- returns: a `Set` of pending `NSManagedObject`s that were updated to the transaction. - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were updated in the transaction.
*/ */
@warn_unused_result public func updatedObjects<T: DynamicObject>(_ entity: T.Type) -> Set<T> {
public func updatedObjects() -> Set<NSManagedObject> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue." "Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access updated objects from an already committed \(cs_typeName(self))." "Attempted to access updated objects from an already committed \(cs_typeName(self))."
) )
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
return self.context.updatedObjects
}
/**
Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
*/
@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 })
} }
/** /**
@@ -344,144 +294,127 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObjectID`s that were updated in the transaction. - returns: a `Set` of pending `NSManagedObjectID`s that were updated in the transaction.
*/ */
@warn_unused_result
public func updatedObjectIDs() -> Set<NSManagedObjectID> { public func updatedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue." "Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))." "Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
) )
return Set(self.context.updatedObjects.map { $0.objectID }) return Set(self.context.updatedObjects.map { $0.objectID })
} }
/** /**
Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called. Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction. - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/ */
@warn_unused_result public func updatedObjectIDs<T: DynamicObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
public func updatedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue." "Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))." "Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
) )
return Set(self.context.updatedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
} }
/** /**
Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `commit()` method was called. Returns all pending `DynamicObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- returns: a `Set` of pending `NSManagedObject`s that were deleted from the transaction. - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `DynamicObject`s of the specified type that were deleted from the transaction.
*/ */
@warn_unused_result public func deletedObjects<T: DynamicObject>(_ entity: T.Type) -> Set<T> {
public func deletedObjects() -> Set<NSManagedObject> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue." "Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access deleted objects from an already committed \(cs_typeName(self))." "Attempted to access deleted objects from an already committed \(cs_typeName(self))."
) )
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? entity.cs_fromRaw(object: $0) : nil }))
return self.context.deletedObjects
}
/**
Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
*/
@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 })
} }
/** /**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/ */
@warn_unused_result
public func deletedObjectIDs() -> Set<NSManagedObjectID> { public func deletedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue." "Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))." "Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
) )
return Set(self.context.deletedObjects.map { $0.objectID }) return Set(self.context.deletedObjects.map { $0.objectID })
} }
/** /**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called.
- parameter entity: the `NSManagedObject` subclass to filter - parameter entity: the `DynamicObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/ */
@warn_unused_result public func deletedObjectIDs<T: DynamicObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
public func deletedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert( CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(), self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue." "Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
) )
CoreStore.assert( CoreStore.assert(
!self.isCommitted, !self.isCommitted,
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))." "Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
) )
return Set(self.context.deletedObjects.flatMap({ entity.cs_matches(object: $0) ? $0.objectID : nil }))
return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
} }
// MARK: 3rd Party Utilities
/**
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
transaction.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
*/
public let userInfo = UserInfo()
// MARK: Internal // MARK: Internal
internal let context: NSManagedObjectContext internal let context: NSManagedObjectContext
internal let transactionQueue: GCDQueue internal let transactionQueue: DispatchQueue
internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue") internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childTransactionQueue")
internal let supportsUndo: Bool internal let supportsUndo: Bool
internal let bypassesQueueing: Bool internal let bypassesQueueing: Bool
internal var isCommitted = false internal var isCommitted = false
internal var result: SaveResult? internal var result: (hasChanges: Bool, error: CoreStoreError?)?
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, supportsUndo: Bool, bypassesQueueing: Bool) { internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
let context = mainContext.temporaryContextInTransactionWithConcurrencyType( let context = mainContext.temporaryContextInTransactionWithConcurrencyType(
queue == .Main queue == .main
? .MainQueueConcurrencyType ? .mainQueueConcurrencyType
: .PrivateQueueConcurrencyType : .privateQueueConcurrencyType
) )
self.transactionQueue = queue self.transactionQueue = queue
self.context = context self.context = context
@@ -489,18 +422,64 @@ public /*abstract*/ class BaseDataTransaction {
self.bypassesQueueing = bypassesQueueing self.bypassesQueueing = bypassesQueueing
context.parentTransaction = self context.parentTransaction = self
context.isTransactionContext = true
if !supportsUndo { if !supportsUndo {
context.undoManager = nil context.undoManager = nil
} }
else if context.undoManager == nil { else if context.undoManager == nil {
context.undoManager = NSUndoManager() context.undoManager = UndoManager()
} }
} }
internal func isRunningInAllowedQueue() -> Bool { 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

@@ -40,31 +40,26 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
/** /**
Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once. Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once.
- parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block. - parameter success: the block executed if the save succeeds.
- parameter failure: the block executed if the save fails. A `CSError` is reported as the argument of the block.
*/ */
@objc @objc
public func commitWithCompletion(completion: ((result: CSSaveResult) -> Void)?) { public func commitWithSuccess(_ success: (() -> Void)?, failure: ((CSError) -> Void)?) {
self.bridgeToSwift.commit { (result) in CoreStore.assert(
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.bridgeToSwift.autoCommit { (result) in
completion?(result: result.bridgeToObjectiveC) switch result {
}
}
/** case (_, nil): success?()
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitWithCompletion:` method was already called once. case (_, let error?): failure?(error.bridgeToObjectiveC)
- 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
closure(transaction: transaction.bridgeToObjectiveC)
} }
} }
} }
@@ -74,7 +69,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
public override var description: String { 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. - returns: a new `NSManagedObject` instance of the specified entity type.
*/ */
@objc @objc
public override func createInto(into: CSInto) -> AnyObject { public override func createInto(_ into: CSInto) -> Any {
return self.bridgeToSwift.create(into.bridgeToSwift) return self.bridgeToSwift.create(into.bridgeToSwift)
} }
@@ -99,8 +94,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
@objc @objc
@warn_unused_result public override func editObject(_ object: NSManagedObject?) -> Any? {
public override func editObject(object: NSManagedObject?) -> AnyObject? {
return self.bridgeToSwift.edit(object) return self.bridgeToSwift.edit(object)
} }
@@ -113,8 +107,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
@objc @objc
@warn_unused_result public override func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
public override func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID) return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
} }
@@ -125,7 +118,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- parameter object: the `NSManagedObject` type to be deleted - parameter object: the `NSManagedObject` type to be deleted
*/ */
@objc @objc
public override func deleteObject(object: NSManagedObject?) { public override func deleteObject(_ object: NSManagedObject?) {
self.bridgeToSwift.delete(object) self.bridgeToSwift.delete(object)
} }
@@ -136,7 +129,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
- parameter objects: the `NSManagedObject`s type to be deleted - parameter objects: the `NSManagedObject`s type to be deleted
*/ */
@objc @objc
public override func deleteObjects(objects: [NSManagedObject]) { public override func deleteObjects(_ objects: [NSManagedObject]) {
self.bridgeToSwift.delete(objects) self.bridgeToSwift.delete(objects)
} }
@@ -144,7 +137,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
internal typealias SwiftType = AsynchronousDataTransaction public typealias SwiftType = AsynchronousDataTransaction
public override var bridgeToSwift: AsynchronousDataTransaction { public override var bridgeToSwift: AsynchronousDataTransaction {
@@ -153,21 +146,59 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
public required init(_ swiftValue: AsynchronousDataTransaction) { public required init(_ swiftValue: AsynchronousDataTransaction) {
super.init(swiftValue) super.init(swiftValue as BaseDataTransaction)
} }
public required init(_ swiftValue: BaseDataTransaction) { public required init(_ swiftValue: BaseDataTransaction) {
fatalError("init(_:) requires an AsynchronousDataTransaction instance") super.init(swiftValue as! AsynchronousDataTransaction)
}
// MARK: Deprecated
@available(*, deprecated, message: "Use the new -[CSAsynchronousDataTransaction commitWithSuccess:failure:] method.")
@objc
public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
CoreStore.assert(
self.bridgeToSwift.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
!self.bridgeToSwift.isCommitted,
"Attempted to commit a \(cs_typeName(self)) more than once."
)
self.bridgeToSwift.commit { (result) in
completion?(result.bridgeToObjectiveC)
}
}
@available(*, deprecated, message: "Secondary tasks spawned from CSAsynchronousDataTransactions and CSSynchronousDataTransactions are no longer supported. ")
@objc
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return bridge {
self.bridgeToSwift.beginSynchronous { (transaction) in
closure(transaction.bridgeToObjectiveC)
}
}
} }
} }
// MARK: - AsynchronousDataTransaction // MARK: - AsynchronousDataTransaction
extension AsynchronousDataTransaction { extension AsynchronousDataTransaction: CoreStoreSwiftType {
// MARK: 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. - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
public func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
do { return self.bridgeToSwift.context.fetchExisting(object) as NSManagedObject?
return try self.bridgeToSwift.context.existingObjectWithID(object.objectID)
}
catch _ {
return nil
}
} }
/** /**
@@ -58,17 +50,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found. - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
public func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
do { return self.bridgeToSwift.context.fetchExisting(objectID) as NSManagedObject?
return try self.bridgeToSwift.context.existingObjectWithID(objectID)
}
catch _ {
return nil
}
} }
/** /**
@@ -78,10 +62,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` array for objects that exists in the transaction - returns: the `NSManagedObject` array for objects that exists in the transaction
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
public func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
return objects.flatMap { try? self.bridgeToSwift.context.existingObjectWithID($0.objectID) } return self.bridgeToSwift.context.fetchExisting(objects) as [NSManagedObject]
} }
/** /**
@@ -91,10 +74,9 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObject` array for objects that exists in the transaction - returns: the `NSManagedObject` array for objects that exists in the transaction
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
public func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
return objectIDs.flatMap { try? self.bridgeToSwift.context.existingObjectWithID($0) } return self.bridgeToSwift.context.fetchExisting(objectIDs) as [NSManagedObject]
} }
/** /**
@@ -105,8 +87,7 @@ public extension CSBaseDataTransaction {
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s - returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
public func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
CoreStore.assert( CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(), self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -123,8 +104,7 @@ public extension CSBaseDataTransaction {
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s - returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
public func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
CoreStore.assert( CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(), self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -141,14 +121,15 @@ public extension CSBaseDataTransaction {
- returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s - returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
public func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
CoreStore.assert( CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(), self.bridgeToSwift.isRunningInAllowedQueue(),
"Attempted to fetch from a \(cs_typeName(self)) outside its designated queue." "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
) )
return self.bridgeToSwift.context.fetchCount(from, fetchClauses) return self.bridgeToSwift.context
.fetchCount(from, fetchClauses)
.flatMap { NSNumber(value: $0) }
} }
/** /**
@@ -159,8 +140,7 @@ public extension CSBaseDataTransaction {
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
public func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
CoreStore.assert( CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(), self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -180,8 +160,7 @@ 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. - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/ */
@objc @objc
@warn_unused_result public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
public func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
CoreStore.assert( CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(), self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -201,8 +180,7 @@ 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. - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/ */
@objc @objc
@warn_unused_result public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
public func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
CoreStore.assert( CoreStore.assert(
self.bridgeToSwift.isRunningInAllowedQueue(), self.bridgeToSwift.isRunningInAllowedQueue(),

View File

@@ -55,7 +55,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: a new `NSManagedObject` instance of the specified entity type. - returns: a new `NSManagedObject` instance of the specified entity type.
*/ */
@objc @objc
public func createInto(into: CSInto) -> AnyObject { public func createInto(_ into: CSInto) -> Any {
return self.bridgeToSwift.create(into.bridgeToSwift) return self.bridgeToSwift.create(into.bridgeToSwift)
} }
@@ -67,8 +67,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
@objc @objc
@warn_unused_result public func editObject(_ object: NSManagedObject?) -> Any? {
public func editObject(object: NSManagedObject?) -> AnyObject? {
return self.bridgeToSwift.edit(object) return self.bridgeToSwift.edit(object)
} }
@@ -81,8 +80,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
@objc @objc
@warn_unused_result public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
public func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
return self.bridgeToSwift.edit(into.bridgeToSwift, objectID) return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
} }
@@ -93,7 +91,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- parameter object: the `NSManagedObject` to be deleted - parameter object: the `NSManagedObject` to be deleted
*/ */
@objc @objc
public func deleteObject(object: NSManagedObject?) { public func deleteObject(_ object: NSManagedObject?) {
self.bridgeToSwift.delete(object) self.bridgeToSwift.delete(object)
} }
@@ -104,7 +102,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- parameter objects: the `NSManagedObject`s to be deleted - parameter objects: the `NSManagedObject`s to be deleted
*/ */
@objc @objc
public func deleteObjects(objects: [NSManagedObject]) { public func deleteObjects(_ objects: [NSManagedObject]) {
self.bridgeToSwift.delete(objects) self.bridgeToSwift.delete(objects)
} }
@@ -121,18 +119,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
// MARK: Inspecting Pending Objects // MARK: Inspecting Pending Objects
/**
Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `-commit*:` method was called.
- returns: an `NSSet` of pending `NSManagedObject`s that were inserted to the transaction.
*/
@objc
@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. 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,8 +126,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were inserted to the transaction. - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
*/ */
@objc @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.bridgeToSwift.insertedObjects(entity)
} }
@@ -152,7 +137,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s that were inserted to the transaction. - returns: an `NSSet` of pending `NSManagedObjectID`s that were inserted to the transaction.
*/ */
@objc @objc
@warn_unused_result
public func insertedObjectIDs() -> Set<NSManagedObjectID> { public func insertedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.insertedObjectIDs() return self.bridgeToSwift.insertedObjectIDs()
@@ -165,24 +149,11 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/ */
@objc @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) 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()
}
/** /**
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. 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.
@@ -190,8 +161,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were updated in the transaction. - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
*/ */
@objc @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.bridgeToSwift.updatedObjects(entity)
} }
@@ -202,7 +172,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s that were updated in the transaction. - returns: an `NSSet` of pending `NSManagedObjectID`s that were updated in the transaction.
*/ */
@objc @objc
@warn_unused_result
public func updatedObjectIDs() -> Set<NSManagedObjectID> { public func updatedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.updatedObjectIDs() return self.bridgeToSwift.updatedObjectIDs()
@@ -215,24 +184,11 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction. - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/ */
@objc @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) 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()
}
/** /**
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. 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.
@@ -240,8 +196,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were deleted from the transaction. - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
*/ */
@objc @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.bridgeToSwift.deletedObjects(entity)
} }
@@ -249,11 +204,9 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
/** /**
Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called. Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called.
- parameter entity: the `NSManagedObject` subclass to filter
- returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/ */
@objc @objc
@warn_unused_result
public func deletedObjectIDs() -> Set<NSManagedObjectID> { public func deletedObjectIDs() -> Set<NSManagedObjectID> {
return self.bridgeToSwift.deletedObjectIDs() return self.bridgeToSwift.deletedObjectIDs()
@@ -266,8 +219,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/ */
@objc @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.bridgeToSwift.deletedObjectIDs(entity)
} }
@@ -280,7 +232,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
return ObjectIdentifier(self.bridgeToSwift).hashValue return ObjectIdentifier(self.bridgeToSwift).hashValue
} }
public override func isEqual(object: AnyObject?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSBaseDataTransaction else { guard let object = object as? CSBaseDataTransaction else {
@@ -292,8 +244,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
public typealias SwiftType = BaseDataTransaction
public required init(_ swiftValue: BaseDataTransaction) { public required init(_ swiftValue: BaseDataTransaction) {
self.swiftTransaction = swiftValue self.swiftTransaction = swiftValue
@@ -309,14 +259,28 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
// MARK: Private // MARK: Private
private let swiftTransaction: BaseDataTransaction private let swiftTransaction: BaseDataTransaction
// MARK: Deprecated
@available(*, deprecated, message: "Use -[insertedObjectsOfType:] and pass the specific entity class")
@objc
public func insertedObjects() -> Set<NSManagedObject> {
return self.bridgeToSwift.insertedObjects()
} }
@available(*, deprecated, message: "Use -[updatedObjectsOfType:] and pass the specific entity class")
@objc
public func updatedObjects() -> Set<NSManagedObject> {
// MARK: - BaseDataTransaction return self.bridgeToSwift.updatedObjects()
}
extension BaseDataTransaction: CoreStoreSwiftType {
@available(*, deprecated, message: "Use -[deletedObjectsOfType:] and pass the specific entity class")
// MARK: CoreStoreSwiftType @objc
public func deletedObjects() -> Set<NSManagedObject> {
public typealias ObjectiveCType = CSBaseDataTransaction
return self.bridgeToSwift.deletedObjects()
}
} }

View File

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

View File

@@ -44,11 +44,10 @@ public extension CSCoreStore {
} }
error: &error]; error: &error];
``` ```
- parameter storage: the `CSInMemoryStore` instance - 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. - 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) self.defaultStack.addInMemoryStorage(storage, completion: completion)
} }
@@ -68,13 +67,12 @@ public extension CSCoreStore {
} }
error: &error]; error: &error];
``` ```
- parameter storage: the `CSSQLiteStore` instance - 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 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 - 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. - 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) 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. - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/ */
@objc @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) 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. - 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 @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) return self.defaultStack.requiredMigrationsForSQLiteStore(storage, error: error)
} }

View File

@@ -27,10 +27,9 @@ import Foundation
import CoreData import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSCoreStore // MARK: - CSCoreStore
@available(OSX 10.12, *)
public extension CSCoreStore { public extension CSCoreStore {
/** /**
@@ -40,8 +39,7 @@ public extension CSCoreStore {
- returns: a `CSObjectMonitor` that monitors changes to `object` - returns: a `CSObjectMonitor` that monitors changes to `object`
*/ */
@objc @objc
@warn_unused_result public static func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
public static func monitorObject(object: NSManagedObject) -> CSObjectMonitor {
return self.defaultStack.monitorObject(object) return self.defaultStack.monitorObject(object)
} }
@@ -54,8 +52,7 @@ public extension CSCoreStore {
- returns: a `CSListMonitor` instance that monitors changes to the list - returns: a `CSListMonitor` instance that monitors changes to the list
*/ */
@objc @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) 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. - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/ */
@objc @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( return self.defaultStack.monitorListByCreatingAsynchronously(
createAsynchronously, createAsynchronously,
@@ -86,8 +83,7 @@ public extension CSCoreStore {
- returns: a `CSListMonitor` instance that monitors changes to the list - returns: a `CSListMonitor` instance that monitors changes to the list
*/ */
@objc @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( return self.defaultStack.monitorSectionedListFrom(
from, 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. - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/ */
@objc @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( self.defaultStack.monitorSectionedListByCreatingAsynchronously(
createAsynchronously, 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. - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public static func fetchExistingObject(_ object: NSManagedObject) -> Any? {
public static func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
return self.defaultStack.fetchExistingObject(object) 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. - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public static func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
public static func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
return self.defaultStack.fetchExistingObjectWithID(objectID) return self.defaultStack.fetchExistingObjectWithID(objectID)
} }
@@ -64,8 +62,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObject` array for objects that exists in the transaction - returns: the `NSManagedObject` array for objects that exists in the transaction
*/ */
@objc @objc
@warn_unused_result public static func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
public static func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
return self.defaultStack.fetchExistingObjects(objects) return self.defaultStack.fetchExistingObjects(objects)
} }
@@ -77,8 +74,7 @@ public extension CSCoreStore {
- returns: the `NSManagedObject` array for objects that exists in the transaction - returns: the `NSManagedObject` array for objects that exists in the transaction
*/ */
@objc @objc
@warn_unused_result public static func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
public static func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
return self.defaultStack.fetchExistingObjectsWithIDs(objectIDs) return self.defaultStack.fetchExistingObjectsWithIDs(objectIDs)
} }
@@ -91,8 +87,7 @@ public extension CSCoreStore {
- returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s - returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public static func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
public static func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
return self.defaultStack.fetchOneFrom(from, fetchClauses: fetchClauses) return self.defaultStack.fetchOneFrom(from, fetchClauses: fetchClauses)
} }
@@ -105,8 +100,7 @@ public extension CSCoreStore {
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s - returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public static func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
public static func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
return self.defaultStack.fetchAllFrom(from, fetchClauses: fetchClauses) 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 - returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/ */
@objc @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) 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 - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/ */
@objc @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) 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 - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/ */
@objc @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) 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. - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/ */
@objc @objc
@warn_unused_result public static func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
public static func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
return self.defaultStack.queryValueFrom(from, selectClause: selectClause, queryClauses: queryClauses) 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. - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/ */
@objc @objc
@warn_unused_result public static func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
public static func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
return self.defaultStack.queryAttributesFrom(from, selectClause: selectClause, queryClauses: queryClauses) 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. Returns the entity name-to-class type mapping from the `defaultStack`'s model.
*/ */
@objc @objc
public static var entityClassesByName: [String: NSManagedObject.Type] { public static func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return CoreStore.entityTypesByName return CoreStore.entityTypesByName(for: type)
}
/**
Returns the entity class for the given entity name from the `defaultStack`'s model.
- parameter name: the entity name
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
*/
@objc
public static func entityClassWithName(name: String) -> NSManagedObject.Type? {
return CoreStore.entityTypesByName[name]
} }
/** /**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model. Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
*/ */
@objc @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]; CSSQLiteStore *storage = [CSCoreStore addInMemoryStorageAndWaitAndReturnError:&error];
``` ```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the `defaultStack` - returns: the `CSInMemoryStore` added to the `defaultStack`
*/ */
@objc @objc
public static func addInMemoryStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSInMemoryStore? { @discardableResult
public static func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
return self.defaultStack.addInMemoryStorageAndWaitAndReturnError(error) return self.defaultStack.addInMemoryStorageAndWaitAndReturnError(error)
} }
@@ -90,12 +78,12 @@ public extension CSCoreStore {
``` ```
CSSQLiteStore *storage = [CSCoreStore addSQLiteStorageAndWaitAndReturnError:&error]; CSSQLiteStore *storage = [CSCoreStore addSQLiteStorageAndWaitAndReturnError:&error];
``` ```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the `defaultStack` - returns: the `CSSQLiteStore` added to the `defaultStack`
*/ */
@objc @objc
public static func addSQLiteStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSSQLiteStore? { @discardableResult
public static func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
return self.defaultStack.addSQLiteStorageAndWaitAndReturnError(error) return self.defaultStack.addSQLiteStorageAndWaitAndReturnError(error)
} }
@@ -108,13 +96,13 @@ public extension CSCoreStore {
addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"] addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
error: &error]; error: &error];
``` ```
- parameter storage: the `CSInMemoryStore` - parameter storage: the `CSInMemoryStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the `defaultStack` - returns: the `CSInMemoryStore` added to the `defaultStack`
*/ */
@objc @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) return self.defaultStack.addInMemoryStorageAndWait(storage, error: error)
} }
@@ -127,14 +115,31 @@ public extension CSCoreStore {
addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"] addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
error: &error]; error: &error];
``` ```
- parameter storage: the `CSSQLiteStore` - parameter storage: the `CSSQLiteStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the `defaultStack` - returns: the `CSSQLiteStore` added to the `defaultStack`
*/ */
@objc @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) 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`. - 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 @objc
public static func beginAsynchronous(closure: (transaction: CSAsynchronousDataTransaction) -> Void) { public static func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
return CoreStore.beginAsynchronous { (transaction) in self.defaultStack.beginAsynchronous(closure)
closure(transaction: transaction.bridgeToObjectiveC)
}
} }
/** /**
@@ -51,15 +48,9 @@ public extension CSCoreStore {
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/ */
@objc @objc
public static func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? { public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void, error: NSErrorPointer) -> Bool {
return bridge { return self.defaultStack.beginSynchronous(closure, error: error)
CoreStore.beginSynchronous { (transaction) in
closure(transaction: transaction.bridgeToObjectiveC)
}
}
} }
/** /**
@@ -69,7 +60,6 @@ public extension CSCoreStore {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made. - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/ */
@objc @objc
@warn_unused_result
public static func beginUnsafe() -> CSUnsafeDataTransaction { public static func beginUnsafe() -> CSUnsafeDataTransaction {
return bridge { return bridge {
@@ -85,8 +75,7 @@ public extension CSCoreStore {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made. - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/ */
@objc @objc
@warn_unused_result public static func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
public static func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
return bridge { return bridge {
@@ -102,4 +91,15 @@ public extension CSCoreStore {
CoreStore.refreshAndMergeAllObjects() CoreStore.refreshAndMergeAllObjects()
} }
// MARK: Deprecated
@available(*, deprecated, message: "Use the new +[CSCoreStore beginSynchronous:error:] API that reports failure using an error instance.")
@objc
@discardableResult
public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return self.defaultStack.beginSynchronous(closure)
}
} }

View File

@@ -44,12 +44,11 @@ public extension CSDataStack {
} }
error: &error]; error: &error];
``` ```
- parameter storage: the `CSInMemoryStore` instance - 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. - 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 @objc
public func addInMemoryStorage(storage: CSInMemoryStore, completion: (CSSetupResult) -> Void) { public func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) {
self.bridgeToSwift.addStorage( self.bridgeToSwift.addStorage(
storage.bridgeToSwift, storage.bridgeToSwift,
@@ -72,14 +71,13 @@ public extension CSDataStack {
} }
error: &error]; error: &error];
``` ```
- parameter storage: the `CSSQLiteStore` instance - 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 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 - 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. - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/ */
@objc @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) { 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. - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
*/ */
@objc @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) { return bridge(error) {
@@ -118,8 +116,7 @@ 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. - 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 @objc
@warn_unused_result public func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
public func requiredMigrationsForSQLiteStore(storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
return bridge(error) { return bridge(error) {

View File

@@ -27,10 +27,9 @@ import Foundation
import CoreData import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSDataStack // MARK: - CSDataStack
@available(OSX 10.12, *)
public extension CSDataStack { public extension CSDataStack {
/** /**
@@ -40,13 +39,9 @@ public extension CSDataStack {
- returns: a `ObjectMonitor` that monitors changes to `object` - returns: a `ObjectMonitor` that monitors changes to `object`
*/ */
@objc @objc
@warn_unused_result public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
public func monitorObject(object: NSManagedObject) -> CSObjectMonitor {
return bridge { return self.bridgeToSwift.monitorObject(object).bridgeToObjectiveC
self.bridgeToSwift.monitorObject(object)
}
} }
/** /**
@@ -57,29 +52,25 @@ public extension CSDataStack {
- returns: a `CSListMonitor` instance that monitors changes to the list - returns: a `CSListMonitor` instance that monitors changes to the list
*/ */
@objc @objc
@warn_unused_result public func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
public func monitorListFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread." "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
) )
CoreStore.assert( CoreStore.assert(
fetchClauses.contains { $0 is CSOrderBy }, fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires a CSOrderBy clause." "A CSListMonitor requires a CSOrderBy clause."
) )
return bridge { return ListMonitor(
ListMonitor(
dataStack: self.bridgeToSwift, dataStack: self.bridgeToSwift,
from: from.bridgeToSwift, from: from.bridgeToSwift,
sectionBy: nil, sectionBy: nil,
applyFetchClauses: { fetchRequest in applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) } 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. - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
*/ */
@objc @objc
public func monitorListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) { public func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread." "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
) )
CoreStore.assert( CoreStore.assert(
@@ -104,9 +95,9 @@ public extension CSDataStack {
dataStack: self.bridgeToSwift, dataStack: self.bridgeToSwift,
from: from.bridgeToSwift, from: from.bridgeToSwift,
sectionBy: nil, sectionBy: nil,
applyFetchClauses: { fetchRequest in applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) } fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
}, },
createAsynchronously: { createAsynchronously: {
@@ -124,29 +115,25 @@ public extension CSDataStack {
- returns: a `CSListMonitor` instance that monitors changes to the list - returns: a `CSListMonitor` instance that monitors changes to the list
*/ */
@objc @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( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread." "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
) )
CoreStore.assert( CoreStore.assert(
fetchClauses.contains { $0 is CSOrderBy }, fetchClauses.contains { $0 is CSOrderBy },
"A CSListMonitor requires an CSOrderBy clause." "A CSListMonitor requires an CSOrderBy clause."
) )
return bridge { return ListMonitor(
ListMonitor(
dataStack: self.bridgeToSwift, dataStack: self.bridgeToSwift,
from: from.bridgeToSwift, from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift, sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { fetchRequest in applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) } 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 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. - 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( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to observe objects from \(cs_typeName(self)) outside the main thread." "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
) )
CoreStore.assert( CoreStore.assert(
@@ -171,9 +158,9 @@ public extension CSDataStack {
dataStack: self.bridgeToSwift, dataStack: self.bridgeToSwift,
from: from.bridgeToSwift, from: from.bridgeToSwift,
sectionBy: sectionBy.bridgeToSwift, sectionBy: sectionBy.bridgeToSwift,
applyFetchClauses: { fetchRequest in applyFetchClauses: { (fetchRequest) in
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) } fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
}, },
createAsynchronously: { 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. - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
public func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
do { return self.bridgeToSwift.mainContext.fetchExisting(object) as NSManagedObject?
return try self.bridgeToSwift.mainContext.existingObjectWithID(object.objectID)
}
catch _ {
return nil
}
} }
/** /**
@@ -58,17 +50,9 @@ public extension CSDataStack {
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found. - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
public func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
do { return self.bridgeToSwift.mainContext.fetchExisting(objectID) as NSManagedObject?
return try self.bridgeToSwift.mainContext.existingObjectWithID(objectID)
}
catch _ {
return nil
}
} }
/** /**
@@ -78,10 +62,9 @@ public extension CSDataStack {
- returns: the `NSManagedObject` array for objects that exists in the transaction - returns: the `NSManagedObject` array for objects that exists in the transaction
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
public func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
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 - returns: the `NSManagedObject` array for objects that exists in the transaction
*/ */
@objc @objc
@warn_unused_result public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
public func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
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 - returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
public func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread." "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
) )
return self.bridgeToSwift.mainContext.fetchOne(from, fetchClauses) return self.bridgeToSwift.mainContext.fetchOne(from, fetchClauses)
@@ -123,11 +104,10 @@ public extension CSDataStack {
- returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s - returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
public func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread." "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
) )
return self.bridgeToSwift.mainContext.fetchAll(from, fetchClauses) 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 - returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
public func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread." "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 - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
public func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread." "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
) )
return self.bridgeToSwift.mainContext.fetchObjectID(from, fetchClauses) 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 - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
*/ */
@objc @objc
@warn_unused_result public func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
public func fetchObjectIDsFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to fetch from a \(cs_typeName(self)) outside the main thread." "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
) )
return self.bridgeToSwift.mainContext.fetchObjectIDs(from, fetchClauses) 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. - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/ */
@objc @objc
@warn_unused_result public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
public func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread." "Attempted to query from a \(cs_typeName(self)) outside the main thread."
) )
return self.bridgeToSwift.mainContext.queryValue(from, selectClause, queryClauses) 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. - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
*/ */
@objc @objc
@warn_unused_result public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
public func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
CoreStore.assert( CoreStore.assert(
NSThread.isMainThread(), Thread.isMainThread,
"Attempted to query from a \(cs_typeName(self)) outside the main thread." "Attempted to query from a \(cs_typeName(self)) outside the main thread."
) )
return self.bridgeToSwift.mainContext.queryAttributes(from, selectClause, queryClauses) 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`. - 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 @objc
public func beginAsynchronous(closure: (transaction: CSAsynchronousDataTransaction) -> Void) { public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
return self.bridgeToSwift.beginAsynchronous { (transaction) in self.bridgeToSwift.perform(
asynchronous: { (transaction) in
closure(transaction: transaction.bridgeToObjectiveC) let csTransaction = transaction.bridgeToObjectiveC
closure(csTransaction)
if !transaction.isCommitted && transaction.hasChanges {
CoreStore.log(
.warning,
message: "The closure for the \(cs_typeName(csTransaction)) completed without being committed. All changes made within the transaction were discarded."
)
} }
try transaction.cancel()
},
completion: { _ in }
)
} }
/** /**
Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. Begins a transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made.
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously - parameter error: the `CSError` pointer that indicates the reason in case of an failure
- returns: `YES` if the commit succeeded, `NO` if the commit failed. If `NO`, the `error` argument will hold error information.
*/ */
@objc @objc
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. - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/ */
@objc @objc
@warn_unused_result
public func beginUnsafe() -> CSUnsafeDataTransaction { public func beginUnsafe() -> CSUnsafeDataTransaction {
return bridge { return bridge {
@@ -85,8 +115,7 @@ public extension CSDataStack {
- returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made. - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/ */
@objc @objc
@warn_unused_result public func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
public func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
return bridge { return bridge {
@@ -102,4 +131,21 @@ public extension CSDataStack {
self.bridgeToSwift.refreshAndMergeAllObjects() self.bridgeToSwift.refreshAndMergeAllObjects()
} }
// MARK: Deprecated
@available(*, deprecated, message: "Use the new -[CSDataStack beginSynchronous:error:] API that reports failure using an error instance.")
@objc
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
return bridge {
self.bridgeToSwift.beginSynchronous { (transaction) in
closure(transaction.bridgeToObjectiveC)
}
}
}
} }

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`. Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set. - parameter xcodeModelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used. - parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack. - parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/ */
@objc @objc
public convenience init(modelName: String?, bundle: NSBundle?, versionChain: [String]?) { public convenience init(xcodeModelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init( self.init(
DataStack( DataStack(
modelName: modelName ?? DataStack.applicationName, xcodeModelName: xcodeModelName ?? DataStack.applicationName,
bundle: bundle ?? NSBundle.mainBundle(), bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
) )
) )
} }
/**
Initializes a `CSDataStack` from the model with the specified `modelName` in the specified `bundle`.
- parameter modelName: the name of the (.xcdatamodeld) model file. If not specified, the application name (CFBundleName) will be used if it exists, or "CoreData" if it the bundle name was not set.
- parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
- parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
*/
@objc
public convenience init(modelName: String?, bundle: 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. 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 @objc
public var entityClassesByName: [String: NSManagedObject.Type] { public func entityTypesByNameForType(_ type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
return self.bridgeToSwift.entityTypesByName return self.bridgeToSwift.entityTypesByName(for: type)
}
/**
Returns the entity class for the given entity name from the stack's's model.
- parameter name: the entity name
- returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
*/
@objc
public func entityClassWithName(name: String) -> NSManagedObject.Type? {
return self.bridgeToSwift.entityTypesByName[name]
} }
/** /**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from stack's model. Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from stack's model.
*/ */
@objc @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]; CSSQLiteStore *storage = [dataStack addInMemoryStorageAndWaitAndReturnError:&error];
``` ```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the stack - returns: the `CSInMemoryStore` added to the stack
*/ */
@objc @objc
public func addInMemoryStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSInMemoryStore? { @discardableResult
public func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
return bridge(error) { 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]; CSSQLiteStore *storage = [dataStack addSQLiteStorageAndWaitAndReturnError:&error];
``` ```
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the stack - returns: the `CSSQLiteStore` added to the stack
*/ */
@objc @objc
public func addSQLiteStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSSQLiteStore? { @discardableResult
public func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
return bridge(error) { 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"] addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
error: &error]; error: &error];
``` ```
- parameter storage: the `CSInMemoryStore` - parameter storage: the `CSInMemoryStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSInMemoryStore` added to the stack - returns: the `CSInMemoryStore` added to the stack
*/ */
@objc @objc
public func addInMemoryStorageAndWait(storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? { @discardableResult
public func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
return bridge(error) { return bridge(error) {
@@ -222,13 +158,13 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"] addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
error: &error]; error: &error];
``` ```
- parameter storage: the `CSSQLiteStore` - parameter storage: the `CSSQLiteStore`
- parameter error: the `NSError` pointer that indicates the reason in case of an failure - parameter error: the `NSError` pointer that indicates the reason in case of an failure
- returns: the `CSSQLiteStore` added to the stack - returns: the `CSSQLiteStore` added to the stack
*/ */
@objc @objc
public func addSQLiteStorageAndWait(storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? { @discardableResult
public func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
return bridge(error) { return bridge(error) {
@@ -244,7 +180,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
return ObjectIdentifier(self.bridgeToSwift).hashValue 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 { guard let object = object as? CSDataStack else {
@@ -255,7 +191,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
public override var description: String { 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 self.bridgeToSwift = swiftValue
super.init() super.init()
} }
// MARK: Deprecated
@available(*, deprecated, message: "Use the -[initWithXcodeModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(modelName: XcodeDataModelFileName?, bundle: Bundle?, versionChain: [String]?) {
self.init(
DataStack(
xcodeModelName: modelName ?? DataStack.applicationName,
bundle: bundle ?? Bundle.main,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionChain:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionChain: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the -[initWithModelName:bundle:versionTree:] initializer.")
@objc
public convenience init(model: NSManagedObjectModel, versionTree: [String]?) {
self.init(
DataStack(
model: model,
migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
)
)
}
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public var entityClassesByName: [EntityName: NSManagedObject.Type] {
return self.bridgeToSwift.entityTypesByName
}
@available(*, deprecated, message: "Use the new -entityTypesByNameForType: method passing `[NSManagedObject class]` as argument.")
@objc
public func entityClassWithName(_ name: EntityName) -> NSManagedObject.Type? {
return self.bridgeToSwift.entityTypesByName[name]
}
} }
@@ -277,5 +267,8 @@ extension DataStack: CoreStoreSwiftType {
// MARK: 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 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 { guard let object = object as? CSError else {
@@ -64,7 +64,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
public override var description: String { 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 return swift
} }
let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
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)
self.swiftError = swift self.swiftError = swift
return swift return swift
} }
@@ -138,43 +87,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
public init(_ swiftValue: CoreStoreError) { public init(_ swiftValue: CoreStoreError) {
self.swiftError = swiftValue self.swiftError = swiftValue
super.init(domain: CoreStoreError.errorDomain, code: swiftValue.errorCode, userInfo: swiftValue.errorUserInfo)
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)
} }
public required init?(coder aDecoder: NSCoder) { public required init?(coder aDecoder: NSCoder) {
@@ -203,33 +116,43 @@ public enum CSErrorCode: Int {
/** /**
A failure occured because of an unknown error. 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`. 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. 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. 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. 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 // MARK: - CoreStoreError
extension CoreStoreError: CoreStoreSwiftType { extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
@@ -237,12 +160,90 @@ extension CoreStoreError: CoreStoreSwiftType {
return CSError(self) 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 // MARK: Internal
internal extension ErrorType { internal extension Error {
internal var bridgeToSwift: CoreStoreError { internal var bridgeToSwift: CoreStoreError {
@@ -254,11 +255,11 @@ internal extension ErrorType {
case let error as CSError: case let error as CSError:
return error.bridgeToSwift return error.bridgeToSwift
case let error as NSError where self.dynamicType is NSError.Type: case let error as NSError where type(of: self) is NSError.Type:
return .InternalError(NSError: error) return .internalError(NSError: error)
default: default:
return .Unknown return .unknown
} }
} }

View File

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

View File

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

View File

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

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSListMonitor // MARK: - CSListMonitor
/** /**
@@ -36,8 +34,9 @@ import CoreData
- SeeAlso: `ListMonitor` - SeeAlso: `ListMonitor`
*/ */
@available(OSX 10.12, *)
@objc @objc
public final class CSListMonitor: NSObject, CoreStoreObjectiveCType { public final class CSListMonitor: NSObject {
// MARK: Public (Accessors) // MARK: Public (Accessors)
@@ -48,7 +47,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSManagedObject` at the specified index - returns: the `NSManagedObject` at the specified index
*/ */
@objc @objc
public subscript(index: Int) -> AnyObject { public subscript(index: Int) -> Any {
return self.bridgeToSwift[index] 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 - returns: the `NSManagedObject` at the specified index, or `nil` if out of bounds
*/ */
@objc @objc
public func objectAtSafeIndex(index: Int) -> AnyObject? { public func objectAtSafeIndex(_ index: Int) -> Any? {
return self.bridgeToSwift[safeIndex: index] 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 - returns: the `NSManagedObject` at the specified section and item index
*/ */
@objc @objc
public func objectAtSectionIndex(sectionIndex: Int, itemIndex: Int) -> AnyObject { public func objectAtSectionIndex(_ sectionIndex: Int, itemIndex: Int) -> Any {
return self.bridgeToSwift[sectionIndex, itemIndex] 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. 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`. - 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 - returns: the `NSManagedObject` at the specified section and item index, or `nil` if out of bounds
*/ */
@objc @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] 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 - returns: the `NSManagedObject` at the specified index path
*/ */
@objc @objc
public func objectAtIndexPath(indexPath: NSIndexPath) -> AnyObject { public func objectAtIndexPath(_ indexPath: IndexPath) -> Any {
return self.bridgeToSwift[indexPath] 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 - returns: the `NSManagedObject` at the specified index path, or `nil` if out of bounds
*/ */
@objc @objc
public func objectAtSafeIndexPath(indexPath: NSIndexPath) -> AnyObject? { public func objectAtSafeIndexPath(_ indexPath: IndexPath) -> Any? {
return self.bridgeToSwift[safeIndexPath: indexPath] 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 - returns: `YES` if at least one object in any section exists, `NO` otherwise
*/ */
@objc @objc
@warn_unused_result
public func hasObjects() -> Bool { public func hasObjects() -> Bool {
return self.bridgeToSwift.hasObjects() 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 - returns: `YES` if at least one object in the specified section exists, `NO` otherwise
*/ */
@objc @objc
@warn_unused_result public func hasObjectsInSection(_ section: Int) -> Bool {
public func hasObjectsInSection(section: Int) -> Bool {
return self.bridgeToSwift.hasObjectsInSection(section) return self.bridgeToSwift.hasObjectsInSection(section)
} }
@@ -146,7 +141,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: all objects in all sections - returns: all objects in all sections
*/ */
@objc @objc
@warn_unused_result
public func objectsInAllSections() -> [NSManagedObject] { public func objectsInAllSections() -> [NSManagedObject] {
return self.bridgeToSwift.objectsInAllSections() return self.bridgeToSwift.objectsInAllSections()
@@ -159,8 +153,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: all objects in the specified section - returns: all objects in the specified section
*/ */
@objc @objc
@warn_unused_result public func objectsInSection(_ section: Int) -> [NSManagedObject] {
public func objectsInSection(section: Int) -> [NSManagedObject] {
return self.bridgeToSwift.objectsInSection(section) 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 - returns: all objects in the specified section, or `nil` if out of bounds
*/ */
@objc @objc
@warn_unused_result
public func objectsInSafeSection(safeSectionIndex section: Int) -> [NSManagedObject]? { public func objectsInSafeSection(safeSectionIndex section: Int) -> [NSManagedObject]? {
return self.bridgeToSwift.objectsInSection(safeSectionIndex: section) return self.bridgeToSwift.objectsInSection(safeSectionIndex: section)
@@ -184,7 +176,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of sections - returns: the number of sections
*/ */
@objc @objc
@warn_unused_result
public func numberOfSections() -> Int { public func numberOfSections() -> Int {
return self.bridgeToSwift.numberOfSections() return self.bridgeToSwift.numberOfSections()
@@ -196,7 +187,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of objects in all sections - returns: the number of objects in all sections
*/ */
@objc @objc
@warn_unused_result
public func numberOfObjects() -> Int { public func numberOfObjects() -> Int {
return self.bridgeToSwift.numberOfObjects() return self.bridgeToSwift.numberOfObjects()
@@ -209,8 +199,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the number of objects in the specified section - returns: the number of objects in the specified section
*/ */
@objc @objc
@warn_unused_result public func numberOfObjectsInSection(_ section: Int) -> Int {
public func numberOfObjectsInSection(section: Int) -> Int {
return self.bridgeToSwift.numberOfObjectsInSection(section) 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 - returns: the number of objects in the specified section, or `nil` if out of bounds
*/ */
@objc @objc
@warn_unused_result
public func numberOfObjectsInSafeSection(safeSectionIndex section: Int) -> NSNumber? { 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 - returns: the `NSFetchedResultsSectionInfo` for the specified section
*/ */
@objc @objc
@warn_unused_result public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo {
public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo {
return self.bridgeToSwift.sectionInfoAtIndex(section) 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. - returns: the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.
*/ */
@objc @objc
@warn_unused_result
public func sectionInfoAtSafeSectionIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? { public func sectionInfoAtSafeSectionIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
return self.bridgeToSwift.sectionInfoAtIndex(safeSectionIndex: section) return self.bridgeToSwift.sectionInfoAtIndex(safeSectionIndex: section)
@@ -260,7 +248,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- returns: the `NSFetchedResultsSectionInfo`s for all sections - returns: the `NSFetchedResultsSectionInfo`s for all sections
*/ */
@objc @objc
@warn_unused_result
public func sections() -> [NSFetchedResultsSectionInfo] { public func sections() -> [NSFetchedResultsSectionInfo] {
return self.bridgeToSwift.sections() 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. - returns: the target section for the specified "Section Index" title and index.
*/ */
@objc @objc
@warn_unused_result public func targetSectionForSectionIndexTitle(title: String, index: Int) -> Int {
public func targetSectionForSectionIndexTitle(title title: String, index: Int) -> Int {
return self.bridgeToSwift.targetSectionForSectionIndex(title: title, index: index) 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 - returns: the section index titles for all sections
*/ */
@objc @objc
@warn_unused_result
public func sectionIndexTitles() -> [String] { public func sectionIndexTitles() -> [String] {
return self.bridgeToSwift.sectionIndexTitles() 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. - returns: the index of the `NSManagedObject` if it exists in the `CSListMonitor`'s fetched objects, or `nil` if not found.
*/ */
@objc @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. - returns: the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
*/ */
@objc @objc
@warn_unused_result public func indexPathOf(_ object: NSManagedObject) -> IndexPath? {
public func indexPathOf(object: NSManagedObject) -> NSIndexPath? {
return self.bridgeToSwift.indexPathOf(object) return self.bridgeToSwift.indexPathOf(object)
} }
@@ -333,7 +318,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListObserver` to send change notifications to - parameter observer: a `CSListObserver` to send change notifications to
*/ */
@objc @objc
public func addListObserver(observer: CSListObserver) { public func addListObserver(_ observer: CSListObserver) {
let swift = self.bridgeToSwift let swift = self.bridgeToSwift
swift.unregisterObserver(observer) swift.unregisterObserver(observer)
@@ -369,7 +354,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListObjectObserver` to send change notifications to - parameter observer: a `CSListObjectObserver` to send change notifications to
*/ */
public func addListObjectObserver(observer: CSListObjectObserver) { public func addListObjectObserver(_ observer: CSListObjectObserver) {
let swift = self.bridgeToSwift let swift = self.bridgeToSwift
swift.unregisterObserver(observer) swift.unregisterObserver(observer)
@@ -425,7 +410,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListSectionObserver` to send change notifications to - parameter observer: a `CSListSectionObserver` to send change notifications to
*/ */
@objc @objc
public func addListSectionObserver(observer: CSListSectionObserver) { public func addListSectionObserver(_ observer: CSListSectionObserver) {
let swift = self.bridgeToSwift let swift = self.bridgeToSwift
swift.unregisterObserver(observer) swift.unregisterObserver(observer)
@@ -488,7 +473,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
- parameter observer: a `CSListObserver` to unregister notifications to - parameter observer: a `CSListObserver` to unregister notifications to
*/ */
@objc @objc
public func removeListObserver(observer: CSListObserver) { public func removeListObserver(_ observer: CSListObserver) {
self.bridgeToSwift.unregisterObserver(observer) 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. - 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 @objc
public func refetch(fetchClauses: [CSFetchClause]) { public func refetch(_ fetchClauses: [CSFetchClause]) {
self.bridgeToSwift.refetch { (fetchRequest) in 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 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 { guard let object = object as? CSListMonitor else {
@@ -540,7 +525,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
public override var description: String { 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 @nonobjc
public required init<T: NSManagedObject>(_ swiftValue: ListMonitor<T>) { public required init<T: NSManagedObject>(_ swiftValue: ListMonitor<T>) {
self.bridgeToSwift = swiftValue.upcast() self.bridgeToSwift = swiftValue.downcast()
super.init() super.init()
} }
} }
@@ -560,7 +545,8 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
// MARK: - ListMonitor // MARK: - ListMonitor
extension ListMonitor: CoreStoreSwiftType { @available(OSX 10.12, *)
extension ListMonitor where ListMonitor.ObjectType: NSManagedObject {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
@@ -568,6 +554,17 @@ extension ListMonitor: CoreStoreSwiftType {
return CSListMonitor(self) return CSListMonitor(self)
} }
}
#endif
// 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)
}
}

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSListObserver // MARK: - CSListObserver
/** /**
@@ -42,6 +40,7 @@ import CoreData
- SeeAlso: `ListObserver` - SeeAlso: `ListObserver`
*/ */
@available(OSX 10.12, *)
@objc @objc
public protocol CSListObserver: class, AnyObject { public protocol CSListObserver: class, AnyObject {
@@ -51,7 +50,7 @@ public protocol CSListObserver: class, AnyObject {
- parameter monitor: the `CSListMonitor` monitoring the list being observed - parameter monitor: the `CSListMonitor` monitoring the list being observed
*/ */
@objc @objc
optional func listMonitorWillChange(monitor: CSListMonitor) optional func listMonitorWillChange(_ monitor: CSListMonitor)
/** /**
Handles processing right after a change to the observed list occurs 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 - parameter monitor: the `CSListMonitor` monitoring the object being observed
*/ */
@objc @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. 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 - parameter monitor: the `CSListMonitor` monitoring the object being observed
*/ */
@objc @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. 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 - parameter monitor: the `CSListMonitor` monitoring the object being observed
*/ */
@objc @objc
optional func listMonitorDidRefetch(monitor: CSListMonitor) optional func listMonitorDidRefetch(_ monitor: CSListMonitor)
} }
@@ -92,6 +91,7 @@ public protocol CSListObserver: class, AnyObject {
- SeeAlso: `ListObjectObserver` - SeeAlso: `ListObjectObserver`
*/ */
@available(OSX 10.12, *)
@objc @objc
public protocol CSListObjectObserver: CSListObserver { public protocol CSListObjectObserver: CSListObserver {
@@ -103,7 +103,7 @@ public protocol CSListObjectObserver: CSListObserver {
- parameter indexPath: the new `NSIndexPath` for the inserted object - parameter indexPath: the new `NSIndexPath` for the inserted object
*/ */
@objc @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 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 - parameter indexPath: the `NSIndexPath` for the deleted object
*/ */
@objc @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 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 - parameter indexPath: the `NSIndexPath` for the updated object
*/ */
@objc @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 Notifies that an object's index changed
@@ -134,7 +134,7 @@ public protocol CSListObjectObserver: CSListObserver {
- parameter toIndexPath: the new `NSIndexPath` for the moved object - parameter toIndexPath: the new `NSIndexPath` for the moved object
*/ */
@objc @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` - SeeAlso: `ListSectionObserver`
*/ */
@available(OSX 10.12, *)
@objc @objc
public protocol CSListSectionObserver: CSListObjectObserver { public protocol CSListSectionObserver: CSListObjectObserver {
@@ -163,7 +164,7 @@ public protocol CSListSectionObserver: CSListObjectObserver {
- parameter sectionIndex: the new section index for the new section - parameter sectionIndex: the new section index for the new section
*/ */
@objc @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 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 - parameter sectionIndex: the previous section index for the deleted section
*/ */
@objc @objc
optional func listMonitor(monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
} }
#endif

View File

@@ -43,7 +43,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc @objc
public var isSuccess: Bool { public var isSuccess: Bool {
return self.bridgeToSwift.boolValue return self.bridgeToSwift.isSuccess
} }
/** /**
@@ -52,7 +52,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc @objc
public var isFailure: Bool { public var isFailure: Bool {
return !self.bridgeToSwift.boolValue return !self.bridgeToSwift.isSuccess
} }
/** /**
@@ -61,7 +61,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc @objc
public var migrationTypes: [CSMigrationType]? { public var migrationTypes: [CSMigrationType]? {
guard case .Success(let migrationTypes) = self.bridgeToSwift else { guard case .success(let migrationTypes) = self.bridgeToSwift else {
return nil return nil
} }
@@ -74,7 +74,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc @objc
public var error: NSError? { public var error: NSError? {
guard case .Failure(let error) = self.bridgeToSwift else { guard case .failure(let error) = self.bridgeToSwift else {
return nil 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. - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
*/ */
@objc @objc
public func handleSuccess(@noescape success: (migrationTypes: [CSMigrationType]) -> Void, @noescape failure: (error: NSError) -> Void) { public func handleSuccess(_ success: (_ migrationTypes: [CSMigrationType]) -> Void, failure: (_ error: NSError) -> Void) {
switch self.bridgeToSwift { switch self.bridgeToSwift {
case .Success(let migrationTypes): case .success(let migrationTypes):
success(migrationTypes: migrationTypes.map { $0.bridgeToObjectiveC }) success(migrationTypes.map { $0.bridgeToObjectiveC })
case .Failure(let error): case .failure(let error):
failure(error: error.bridgeToObjectiveC) 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. - parameter success: the block to execute on success. The block passes an array of `CSMigrationType`s that indicates the migration steps completed.
*/ */
@objc @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 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. - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
*/ */
@objc @objc
public func handleFailure(@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 return
} }
failure(error: error.bridgeToObjectiveC) failure(error.bridgeToObjectiveC)
} }
@@ -144,7 +144,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue 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 { guard let object = object as? CSMigrationResult else {
@@ -155,7 +155,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
public override var description: String { 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 // 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 @objc
public var needsMigration: Bool { 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 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 { guard let object = object as? CSMigrationType else {
@@ -101,7 +101,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
public override var description: String { 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 // MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSMigrationType public var bridgeToObjectiveC: CSMigrationType {
return CSMigrationType(self)
}
} }

View File

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

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSObjectObserver // MARK: - CSObjectObserver
/** /**
@@ -40,6 +38,7 @@ import CoreData
- SeeAlso: `ObjectObserver` - SeeAlso: `ObjectObserver`
*/ */
@available(OSX 10.12, *)
@objc @objc
public protocol CSObjectObserver: class, AnyObject { public protocol CSObjectObserver: class, AnyObject {
@@ -50,7 +49,7 @@ public protocol CSObjectObserver: class, AnyObject {
- parameter object: the `NSManagedObject` instance being observed - parameter object: the `NSManagedObject` instance being observed
*/ */
@objc @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 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. - 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 @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 Handles processing right after `object` is deleted
@@ -69,7 +68,5 @@ public protocol CSObjectObserver: class, AnyObject {
- parameter object: the `NSManagedObject` instance being observed - parameter object: the `NSManagedObject` instance being observed
*/ */
@objc @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]) fetchAllFrom:CSFromClass([MyPersonEntity class])
fetchClauses:@[CSOrderByKey(CSSortAscending(@"fullname"))]]]; fetchClauses:@[CSOrderByKey(CSSortAscending(@"fullname"))]]];
``` ```
- parameter sortDescriptor: a `NSSortDescriptor` - parameter sortDescriptor: a `NSSortDescriptor`
*/ */
@objc @objc
@@ -69,7 +68,6 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
fetchAllFrom:CSFromClass([MyPersonEntity class]) fetchAllFrom:CSFromClass([MyPersonEntity class])
fetchClauses:@[CSOrderByKeys(CSSortAscending(@"fullname"), CSSortDescending(@"age"), nil))]]]; fetchClauses:@[CSOrderByKeys(CSSortAscending(@"fullname"), CSSortDescending(@"age"), nil))]]];
``` ```
- parameter sortDescriptors: an array of `NSSortDescriptor`s - parameter sortDescriptors: an array of `NSSortDescriptor`s
*/ */
@objc @objc
@@ -86,7 +84,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
return self.bridgeToSwift.hashValue 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 { guard let object = object as? CSOrderBy else {
@@ -97,14 +95,14 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
public override var description: String { 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 // MARK: CSFetchClause, CSQueryClause, CSDeleteClause
@objc @objc
public func applyToFetchRequest(fetchRequest: NSFetchRequest) { public func applyToFetchRequest(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
self.bridgeToSwift.applyToFetchRequest(fetchRequest) self.bridgeToSwift.applyToFetchRequest(fetchRequest)
} }
@@ -128,5 +126,8 @@ extension OrderBy: CoreStoreSwiftType {
// MARK: 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. Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them. - parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them. - parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`. - parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
*/ */
@objc @objc
public convenience init(fileURL: NSURL, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: Int) { public convenience init(fileURL: URL, configuration: ModelConfiguration, localStorageOptions: Int) {
self.init( self.init(
SQLiteStore( SQLiteStore(
fileURL: fileURL, fileURL: fileURL,
configuration: configuration, configuration: configuration,
mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions) localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
) )
) )
@@ -61,29 +60,27 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/** /**
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist. Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`. - Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them. - parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them. - parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`. - parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
*/ */
@objc @objc
public convenience init(fileName: String, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: Int) { public convenience init(fileName: String, configuration: ModelConfiguration, localStorageOptions: Int) {
self.init( self.init(
SQLiteStore( SQLiteStore(
fileName: fileName, fileName: fileName,
configuration: configuration, configuration: configuration,
mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions) localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
) )
) )
} }
/** /**
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`. Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`. - Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
*/ */
@objc @objc
public convenience override init() { public convenience override init() {
@@ -98,18 +95,18 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
The `NSURL` that points to the SQLite file The `NSURL` that points to the SQLite file
*/ */
@objc @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 @objc
public var mappingModelBundles: [NSBundle] { public var migrationMappingProviders: [Any] {
return self.bridgeToSwift.mappingModelBundles return self.bridgeToSwift.migrationMappingProviders
} }
/** /**
@@ -133,7 +130,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/** /**
The configuration name in the model file The configuration name in the model file
*/ */
public var configuration: String? { public var configuration: ModelConfiguration {
return self.bridgeToSwift.configuration return self.bridgeToSwift.configuration
} }
@@ -145,7 +142,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
``` ```
*/ */
@objc @objc
public var storeOptions: [String: AnyObject]? { public var storeOptions: [AnyHashable: Any]? {
return self.bridgeToSwift.storeOptions 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. Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
*/ */
@objc @objc
public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel, error: NSErrorPointer) -> Bool { public func cs_eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
return bridge(error) { return bridge(error) {
try self.bridgeToSwift.eraseStorageAndWait(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 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 { guard let object = object as? CSSQLiteStore else {
@@ -181,7 +178,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
public override var description: String { 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 self.bridgeToSwift = swiftValue
super.init() super.init()
} }
// MARK: Obsoleted
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileURL:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
fatalError()
}
@available(*, obsoleted: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileName:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
fatalError()
}
} }
@@ -203,5 +217,8 @@ extension SQLiteStore: CoreStoreSwiftType {
// MARK: 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)
}
}

View File

@@ -27,8 +27,6 @@ import Foundation
import CoreData import CoreData
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: - CSSectionBy // MARK: - CSSectionBy
/** /**
@@ -36,6 +34,7 @@ import CoreData
- SeeAlso: `SectionBy` - SeeAlso: `SectionBy`
*/ */
@available(OSX 10.12, *)
@objc @objc
public final class CSSectionBy: NSObject, CoreStoreObjectiveCType { public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
@@ -46,7 +45,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections - returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
*/ */
@objc @objc
public static func keyPath(sectionKeyPath: KeyPath) -> CSSectionBy { public static func keyPath(_ sectionKeyPath: KeyPath) -> CSSectionBy {
return self.init(SectionBy(sectionKeyPath)) return self.init(SectionBy(sectionKeyPath))
} }
@@ -59,7 +58,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
- returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections - returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
*/ */
@objc @objc
public static func keyPath(sectionKeyPath: KeyPath, sectionIndexTransformer: (sectionName: String?) -> String?) -> CSSectionBy { public static func keyPath(_ sectionKeyPath: KeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer)) return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer))
} }
@@ -69,7 +68,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
public override var description: String { public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)" return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
} }
@@ -87,11 +86,13 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
// MARK: - SectionBy // MARK: - SectionBy
@available(OSX 10.12, *)
extension SectionBy: CoreStoreSwiftType { extension SectionBy: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSSectionBy public var bridgeToObjectiveC: CSSectionBy {
}
#endif return CSSectionBy(self)
}
}

View File

@@ -45,13 +45,12 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
select:CSSelectString(CSAttribute(@"fullname")) select:CSSelectString(CSAttribute(@"fullname"))
fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]]; fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
``` ```
- parameter keyPath: the attribute name - parameter keyPath: the attribute name
*/ */
@objc @objc
public convenience init(keyPath: KeyPath) { public convenience init(keyPath: KeyPath) {
self.init(.Attribute(keyPath)) self.init(.attribute(keyPath))
} }
/** /**
@@ -61,15 +60,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
select:[CSSelect numberForTerm:[CSSelectTerm average:@"age" as:nil]]]; select:[CSSelect numberForTerm:[CSSelectTerm average:@"age" as:nil]]];
``` ```
- parameter keyPath: the attribute name - parameter keyPath: the attribute name
- parameter `as`: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average(<attributeName>)" is used - parameter `as`: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average(<attributeName>)" is used
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute
*/ */
@objc @objc
public static func average(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm { public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
return self.init(.Average(keyPath, As: alias)) return self.init(.average(keyPath, as: alias))
} }
/** /**
@@ -79,15 +77,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
select:[CSSelect numberForTerm:[CSSelectTerm count:@"employeeID" as:nil]]]; select:[CSSelect numberForTerm:[CSSelectTerm count:@"employeeID" as:nil]]];
``` ```
- parameter keyPath: the attribute name - parameter keyPath: the attribute name
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count(<attributeName>)" is used - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count(<attributeName>)" is used
- returns: a `SelectTerm` to a `Select` clause for a count query - returns: a `SelectTerm` to a `Select` clause for a count query
*/ */
@objc @objc
public static func count(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm { public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
return self.init(.Count(keyPath, As: alias)) return self.init(.count(keyPath, as: alias))
} }
/** /**
@@ -97,15 +94,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
select:[CSSelect numberForTerm:[CSSelectTerm maximum:@"age" as:nil]]]; select:[CSSelect numberForTerm:[CSSelectTerm maximum:@"age" as:nil]]];
``` ```
- parameter keyPath: the attribute name - parameter keyPath: the attribute name
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max(<attributeName>)" is used - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max(<attributeName>)" is used
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute
*/ */
@objc @objc
public static func maximum(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm { public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
return self.init(.Maximum(keyPath, As: alias)) return self.init(.maximum(keyPath, as: alias))
} }
/** /**
@@ -115,15 +111,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
select:[CSSelect numberForTerm:[CSSelectTerm minimum:@"age" as:nil]]]; select:[CSSelect numberForTerm:[CSSelectTerm minimum:@"age" as:nil]]];
``` ```
- parameter keyPath: the attribute name - parameter keyPath: the attribute name
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min(<attributeName>)" is used - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min(<attributeName>)" is used
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute
*/ */
@objc @objc
public static func minimum(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm { public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
return self.init(.Minimum(keyPath, As: alias)) return self.init(.minimum(keyPath, as: alias))
} }
/** /**
@@ -133,15 +128,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
select:[CSSelect numberForTerm:[CSSelectTerm sum:@"age" as:nil]]]; select:[CSSelect numberForTerm:[CSSelectTerm sum:@"age" as:nil]]];
``` ```
- parameter keyPath: the attribute name - parameter keyPath: the attribute name
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum(<attributeName>)" is used - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum(<attributeName>)" is used
- returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute
*/ */
@objc @objc
public static func sum(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm { public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
return self.init(.Sum(keyPath, As: alias)) return self.init(.sum(keyPath, as: alias))
} }
/** /**
@@ -152,15 +146,13 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]] select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]]
fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]]; fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
``` ```
- parameter keyPath: the attribute name
- parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used
- returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
*/ */
@objc @objc
public static func objectIDAs(alias: KeyPath? = nil) -> CSSelectTerm { public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm {
return self.init(.ObjectID(As: alias)) return self.init(.objectID(as: alias))
} }
@@ -171,7 +163,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
return self.bridgeToSwift.hashValue return self.bridgeToSwift.hashValue
} }
public override func isEqual(object: AnyObject?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSSelectTerm else { guard let object = object as? CSSelectTerm else {
@@ -199,7 +191,10 @@ extension SelectTerm: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
public typealias ObjectiveCType = CSSelectTerm public var bridgeToObjectiveC: CSSelectTerm {
return CSSelectTerm(self)
}
} }
@@ -221,8 +216,7 @@ public final class CSSelect: NSObject {
select:CSSelectNumber(CSAggregateMax(@"age")) select:CSSelectNumber(CSAggregateMax(@"age"))
// ... // ...
``` ```
- parameter numberTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/ */
public convenience init(numberTerm: CSSelectTerm) { public convenience init(numberTerm: CSSelectTerm) {
@@ -237,8 +231,7 @@ public final class CSSelect: NSObject {
select:CSSelectDecimal(CSAggregateAverage(@"price")) select:CSSelectDecimal(CSAggregateAverage(@"price"))
// ... // ...
``` ```
- parameter decimalTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/ */
public convenience init(decimalTerm: CSSelectTerm) { public convenience init(decimalTerm: CSSelectTerm) {
@@ -253,8 +246,7 @@ public final class CSSelect: NSObject {
select:CSSelectString(CSAttribute(@"fullname")) select:CSSelectString(CSAttribute(@"fullname"))
// ... // ...
``` ```
- parameter stringTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/ */
public convenience init(stringTerm: CSSelectTerm) { public convenience init(stringTerm: CSSelectTerm) {
@@ -269,12 +261,11 @@ public final class CSSelect: NSObject {
select:CSSelectDate(CSAggregateMax(@"updatedDate")) select:CSSelectDate(CSAggregateMax(@"updatedDate"))
// ... // ...
``` ```
- parameter dateTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/ */
public convenience init(dateTerm: CSSelectTerm) { public convenience init(dateTerm: CSSelectTerm) {
self.init(Select<NSDate>(dateTerm.bridgeToSwift)) self.init(Select<Date>(dateTerm.bridgeToSwift))
} }
/** /**
@@ -285,12 +276,11 @@ public final class CSSelect: NSObject {
select:CSSelectData(CSAttribute(@"imageData")) select:CSSelectData(CSAttribute(@"imageData"))
// ... // ...
``` ```
- parameter dataTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/ */
public convenience init(dataTerm: CSSelectTerm) { public convenience init(dataTerm: CSSelectTerm) {
self.init(Select<NSData>(dataTerm.bridgeToSwift)) self.init(Select<Data>(dataTerm.bridgeToSwift))
} }
/** /**
@@ -301,12 +291,10 @@ public final class CSSelect: NSObject {
select:CSSelectObjectID() select:CSSelectObjectID()
// ... // ...
``` ```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
*/ */
public convenience init(objectIDTerm: ()) { public convenience init(objectIDTerm: ()) {
self.init(Select<NSManagedObjectID>(.ObjectID())) self.init(Select<NSManagedObjectID>(.objectID()))
} }
/** /**
@@ -316,11 +304,10 @@ public final class CSSelect: NSObject {
queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
select:[CSSelect dictionaryForTerm:[CSSelectTerm maximum:@"age" as:nil]]]; select:[CSSelect dictionaryForTerm:[CSSelectTerm maximum:@"age" as:nil]]];
``` ```
- parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
- returns: a `CSSelect` clause for querying an entity attribute - returns: a `CSSelect` clause for querying an entity attribute
*/ */
public static func dictionaryForTerm(term: CSSelectTerm) -> CSSelect { public static func dictionaryForTerm(_ term: CSSelectTerm) -> CSSelect {
return self.init(Select<NSDictionary>(term.bridgeToSwift)) return self.init(Select<NSDictionary>(term.bridgeToSwift))
} }
@@ -335,11 +322,10 @@ public final class CSSelect: NSObject {
[CSSelectTerm attribute:@"age" as:nil] [CSSelectTerm attribute:@"age" as:nil]
]]]; ]]];
``` ```
- parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query - parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query
- returns: a `CSSelect` clause for querying an entity attribute - returns: a `CSSelect` clause for querying an entity attribute
*/ */
public static func dictionaryForTerms(terms: [CSSelectTerm]) -> CSSelect { public static func dictionaryForTerms(_ terms: [CSSelectTerm]) -> CSSelect {
return self.init(Select<NSDictionary>(terms.map { $0.bridgeToSwift })) return self.init(Select<NSDictionary>(terms.map { $0.bridgeToSwift }))
} }
@@ -350,10 +336,10 @@ public final class CSSelect: NSObject {
public override var hash: Int { public override var hash: Int {
return self.attributeType.hashValue return self.attributeType.hashValue
^ self.selectTerms.map { $0.hashValue }.reduce(0, combine: ^) ^ self.selectTerms.map { $0.hashValue }.reduce(0, ^)
} }
public override func isEqual(object: AnyObject?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSSelect else { guard let object = object as? CSSelect else {
@@ -365,15 +351,15 @@ public final class CSSelect: NSObject {
public override var description: String { public override var description: String {
return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)" return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
} }
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
public init<T: SelectValueResultType>(_ swiftValue: Select<T>) { public init<T: QueryableAttributeType>(_ swiftValue: Select<T>) {
self.attributeType = T.attributeType self.attributeType = T.cs_rawAttributeType
self.selectTerms = swiftValue.selectTerms self.selectTerms = swiftValue.selectTerms
self.bridgeToSwift = swiftValue self.bridgeToSwift = swiftValue
super.init() super.init()
@@ -381,7 +367,7 @@ public final class CSSelect: NSObject {
public init<T: SelectResultType>(_ swiftValue: Select<T>) { public init<T: SelectResultType>(_ swiftValue: Select<T>) {
self.attributeType = .UndefinedAttributeType self.attributeType = .undefinedAttributeType
self.selectTerms = swiftValue.selectTerms self.selectTerms = swiftValue.selectTerms
self.bridgeToSwift = swiftValue self.bridgeToSwift = swiftValue
super.init() super.init()

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